module Relax
# Response is intended to be a parent class for responses passed to
# Service#call.
#
# A response is in essence an object used to facilitate XML parsing. It
# stores an XML document, and provides access to it through methods like
# #element and #attribute.
class Response
attr_accessor :raw
# New takes in and parses the raw response.
#
# This will raise a MissingParameter error if a parameterd marked as
# required is not present in the parsed response.
def initialize(xml)
@raw = xml
@parser = Relax::Parsers::Factory.get(parser_name).new(xml.to_s, self)
end
def parser_name
self.class.instance_variable_get('@parser') || :default
end
def method_missing(method, *args) #:nodoc:
if @parser.respond_to?(method)
@parser.__send__(method, *args)
else
super
end
end
class << self
# When a Response is extended, the superclass's parameters are copied
# into the new class. This behavior has the following side-effect: if
# parameters are added to the superclass after it has been extended,
# those new paramters won't be passed on to its children. This shouldn't
# be a problem in most cases.
def inherited(subclass)
@parameters.each do |name, options|
subclass.parameter(name, options)
end if @parameters
subclass.parser(@parser) if @parser
end
# Specifes a parameter that will be automatically parsed when the
# Response is instantiated.
#
# Options:
# - :attribute: An attribute name to use, or true to
# use the :element value as the attribute name on the root.
# - :collection: A class used to instantiate each item when
# selecting a collection of elements.
# - :element: The XML element name.
# - :object: A class used to instantiate an element.
# - :type: The type of the parameter. Should be one of
# :text, :integer, :float, or :date.
def parameter(name, options = {})
attr_accessor name
@parameters ||= {}
@parameters[name] = options
end
# Specifies the parser to use when decoding the server response. If
# no parser is specified for the response, then the default parser will
# be used.
#
# See Relax::Parsers for a list of available parsers.
def parser(name)
@parser ||= name
end
def ===(response)
response.is_a?(Class) ? response.ancestors.include?(self) : super
end
end
end
end