Class: Response::Base::ServerRsp

Inherits:
Object
  • Object
show all
Defined in:
lib/violet/response.rb

Overview

base class used to handle Violet server’s responses.

We want to access to all xml elements easily, like the powerful ActiveRecord ‘find’ function. This class provide virtual accessor and predicate for elements. If you have a ServerRsp, rsp.has_message? will return true if rsp has a ‘message’ element, and rsp.has_many_messages? will return true if rsp has more than one ‘message’ element. rsp.message will return the first message element and rsp.messages will return an Array that contains all message elements of rsp (see doc of Response module for examples).

Direct Known Subclasses

BadServerRsp, GoodServerRsp, EmptyServerRsp

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw) ⇒ ServerRsp

create a ServerRsp with the raw argument. raw must be the xml text of the server’s response. if the xml is malformed, a REXML::ParseException will be raised.



77
78
79
# File 'lib/violet/response.rb', line 77

def initialize raw
  @xml = REXML::Document.new raw
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object

here some magic code :)



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/violet/response.rb', line 128

def method_missing(name) #:nodoc:
  # this method to transforme REXML::Element into text or hash
  filter = Proc.new do |e|
    e.text || e.attributes.to_hash
  end
  # raise an error when there are no results and method_missing is not a question
  check = Proc.new do |ary|
    if ary.empty?
      raise NameError.new("undefined local variable or method #{$1} for #{self.inspect}")
    else
      ary
    end
  end

  case name.to_s
  when /^has_many_(.+)s\?$/   then get_all($1).size > 1
  when /^has_(.+)\?$/         then get_all($1).size > 0
  when /(.*)s$/               then check.call( get_all($1).collect(&filter) )
  when /(.*)/                 then check.call( get_all($1).collect(&filter) ).first
  end
end

Instance Attribute Details

#xmlObject (readonly)

It’s possible to access the REXML::Document object if needed, but try to use virtual accessors and get_all if possible.



83
84
85
# File 'lib/violet/response.rb', line 83

def xml
  @xml
end

Instance Method Details

#bad?Boolean

return true if the response is an error, false otherwhise.

Returns:

  • (Boolean)


91
92
93
# File 'lib/violet/response.rb', line 91

def bad?
  self.is_a? BadServerRsp
end

#get_all(name) ⇒ Object

Summary

get all xml’s element that match name.

Arguments

name : name of the element you want to fetch (see examples) block : a block of code that take a REXML::Element in parameter. if no block is given, it return an Array of REXML::Element.

Examples

Side effect

>> rsp = Response.parse('<?xml version="1.0" encoding="UTF-8"?><rsp><langListUser nb="4"/><myLang lang="fr"/><myLang lang="us"/><myLang lang="uk"/><myLang lang="de"/></rsp>')
=> #<Response::LangListUser:0x2b16c5e17510 @xml=<UNDEFINED> ... </>>
>> rsp.get_all(:myLang) do |e|
>>   puts "you can use '#{e.attribute('lang').value}'"
>> end
you can use 'fr'
you can use 'us'
you can use 'uk'
you can use 'de'
=> [nil, nil, nil, nil]

usage of returned value

>> langs = rsp.get_all(:myLang) { |e| e.attribute('lang').value }
=> ["fr", "us", "uk", "de"]


120
121
122
123
124
125
# File 'lib/violet/response.rb', line 120

def get_all name
  # REXML::XPath.match(@xml, element).collect do |e|  <= this one is for a recursive search.
  @xml.root.elements.collect(name.to_s) do |e|
    if block_given? then yield(e) else e end
  end
end

#good?Boolean

return true if the response is not an error, false otherwhise.

Returns:

  • (Boolean)


86
87
88
# File 'lib/violet/response.rb', line 86

def good?
  self.is_a? GoodServerRsp
end