lib/relax/response.rb in relax-0.0.4 vs lib/relax/response.rb in relax-0.0.5

- old
+ new

@@ -1,147 +1,47 @@ -require 'rubygems' -require 'hpricot' - -require 'date' - 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 - attr_accessor :xml - - # New takes in the XML from the response. For the initial response, this - # will be the root element, but child elements may also be passed into - # Response objects. + + # 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 XML response. + # required is not present in the parsed response. def initialize(xml) - @raw = xml - @xml = Hpricot.XML(xml.to_s) - - if parameters = self.class.instance_variable_get('@parameters') - parameters.each do |parameter, options| - begin - element = options[:element] || parameter - - if attribute = options[:attribute] and attribute == true - node = attribute(root, element) - elsif attribute - node = attribute(element(element), attribute) - elsif options[:collection] - node = elements(element) - else - node = element(element) - end - - if options[:collection] - value = node.collect do |element| - options[:collection].new(element) - end - else - case type = options[:type] - when Response - value = type.new(node) - - when :date - value = date_value(node) - - when :time - value = time_value(node) - - when :float - value = float_value(node) - - when :integer - value = integer_value(node) - - when :text - else - value = text_value(node) - end - end - - instance_variable_set("@#{parameter}", value) - rescue Hpricot::Error - raise MissingParameter if options[:required] - end - end - end + @raw = xml + @parser = Relax::Parsers::Factory.get(parser_name).new(xml.to_s, self) end - - # Returns the root of the XML document. - def root - @xml.root + + def parser_name + self.class.instance_variable_get('@parser') || :default end - - # Checks the name of the root node. - def is?(name) - root.name.gsub(/.*:(.*)/, '\1') == node_name(name) + + def method_missing(method, *args) #:nodoc: + if @parser.respond_to?(method) + @parser.__send__(method, *args) + else + super + end end - # Returns an element of the specified name. - def element(name) - root.at(root_path(name)) - end - alias :has? :element - - # Returns an attribute on an element. - def attribute(element, name) - element[name] - end - - # Returns a set of elements matching name. - def elements(name) - root.search(root_path(name)) - end - - # Gets the value of an element or attribute. - def value(value) - value.is_a?(Hpricot::Elem) ? value.inner_text : value.to_s - end - - # Gets a text value. - def text_value(value) - value(value) - end - - # Gets an integer value. - def integer_value(value) - value(value).to_i - end - - # Gets a float value. - def float_value(value) - value(value).to_f - end - - # Gets a date value. - def date_value(value) - Date.parse(value(value)) - end - - # Gets a time value. - def time_value(value) - Time.parse(value(value)) - 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. # @@ -157,24 +57,22 @@ 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 - private - - # Converts a name to a node name. - def node_name(name) - name.to_s - end - - # Gets the XPath expression representing the root node. - def root_path(name) - "/#{node_name(name)}" - end end end