require 'relax/query' module Relax # Request is intended to be a parent class for requests passed to # Service#call. class Request @parameters = {} # New takes an optional hash of default parameter values. When passed, # the values will be set on the request if the key exists as a valid # parameter name. def initialize(defaults = {}) # initialize default parameter values self.class.parameters.each do |parameter, options| if defaults.has_key?(parameter) value = defaults[parameter] elsif options[:value] value = options[:value] end instance_variable_set("@#{parameter}", value) if value end end # Converts this request into a Query object. def to_query self.class.parameters.keys.inject(Query.new) do |query, key| value = send(key) options = self.class.parameters[key] if value && !options[:type] query[convert_key(key)] = value if value elsif options[:type] options[:type].parameters.each do |parameter, options| query[convert_complex_key(key, parameter)] = value.send(parameter) if value end end query end end # Converts this request into a query string for use in a URL. def to_s to_query.to_s end # Converts a key when the Request is converted to a query. By default, no # conversion actually takes place, but this method can be overridden by # child classes to perform standard manipulations, such as replacing # underscores. def convert_key(key) key end protected :convert_key # Converts a complex key (i.e. a parameter with a custom type) when the # Request is converted to a query. By default, this means the key name and # the parameter name separated by two underscores. This method can be # overridden by child classes. def convert_complex_key(key, parameter) "#{convert_key(key)}.#{convert_key(parameter)}" end protected :convert_complex_key class << self # Create the parameters hash for the subclass. def inherited(subclass) #:nodoc: subclass.instance_variable_set('@parameters', {}) end # Specifies a parameter to create on the request class. # # Options: # - :type: An optional custom data type for the parameter. # This must be a class that is a descendent of Request. # - :value: The default value for this parameter. def parameter(name, options = {}) attr_accessor name options = @parameters[name].merge(options) if @parameters.has_key?(name) @parameters[name] = options end # Adds a template value to a request class. Equivalent to creating a # parameter with a default value. def []=(key, value) parameter(key, {:value => value}) end # Returns a hash of all of the parameters for this request, including # those that are inherited. def parameters #:nodoc: (superclass.respond_to?(:parameters) ? superclass.parameters : {}).merge(@parameters) end end end end