Class: Consumer::Request
- Inherits:
-
Object
- Object
- Consumer::Request
- Includes:
- Consumer
- Defined in:
- lib/consumer/request.rb
Overview
Class Attrubutes
required
-
Defines attributes that must be present in any instance before calling
do
. Anything defined here but not set in the instance will raise a RequiredFieldError on callingdo
Defaluts to []
response_class
-
String for setting the class the request will use to parse the response.
Defaults to [Something]Request, ex. for a RateRequest, this would default to “Rate”.
Note that the instance method with the same name returns a constant rather than the string set here.
yaml_defaults
-
Consists of two parameters. In order:
-
The location (as a string) for a yaml file containing attribute defaults.
-
A namespace to grab the defaults out of.
If your yaml looked like this:
<pre> ups:
user_id: Woody
usps:
user_id: John
</pre>
UPSRequest would want to use “ups” as the namespace value, where USPSRequest would want to use “usps”
This is optional and has no default
-
error_paths
-
If you define this in your subclasses to return a hash for error options (see “Options” below) they will raise informative RequestError errors with xml error info in the message.
If this is left undefined and the remote server returns error xml rather than what you were expecting, you’ll get generic xml parsing errors instead of something informative.
Note: currently only handles one error.
Options
All options are xpaths. All options except
:root
are relative to the root (unless prefixed with “//”)-
:root
- Root element of the error(s) -
:code
- Remote API’s error code for this error -
:message
- Informative part of the error
Example
<pre>
:root => "//Error", :code => "ErrorCode", :message => "LongDescription"
</pre>
Anything passed in to initialize will override these, though.
-
Defined Under Namespace
Classes: RequestError, RequiredFieldError
Constant Summary
Constants included from Consumer
Instance Attribute Summary collapse
-
#request_xml ⇒ Object
readonly
Returns the value of attribute request_xml.
-
#response_xml ⇒ Object
readonly
Returns the value of attribute response_xml.
Class Method Summary collapse
- .basic_authentication(*args) ⇒ Object
- .defaults(defaults = nil) ⇒ Object
- .do(args = {}) ⇒ Object
- .error_paths(options = nil) ⇒ Object
- .request_pass(pass = nil) ⇒ Object
- .request_user(user = nil) ⇒ Object
- .required(*args) ⇒ Object
- .response_class(klass = nil) ⇒ Object
- .url(url = nil) ⇒ Object
- .yaml_defaults(*args) ⇒ Object
Instance Method Summary collapse
- #config_root ⇒ Object
- #defaults ⇒ Object
-
#do ⇒ Object
Sends self.to_xml to self.url and returns new object(s) created via [response_class].from_xml === Prerequisites * All attributes in self.required must exist; raises RequiredFieldError otherwise * self.to_xml must be defined; RuntimeError otherwise * self.url must be set; RuntimeError otherwise * response_class.from_xml must be defined; RuntimeError otherwise === Returns Whatever response_class.from_xml(@response_xml) returns, which should be an object or array of objects (an array of objects if response_class is using Consumer::Mapping).
- #error_paths ⇒ Object
-
#initialize(attrs = {}) ⇒ Request
constructor
First gets defaults from self.defaults, merges them with defaults from
yaml_defaults
, merges all that with passed in attrs, and initializes all those into instance variables for use in to_xml. - #request_pass ⇒ Object
- #request_user ⇒ Object
- #required ⇒ Object
-
#response_class ⇒ Object
returns self.class.response_class as a constant (not a string).
-
#to_xml_etc ⇒ Object
Gets called during do instead of just to_xml, and does a bit more than just return xml.
- #url ⇒ Object
- #yaml_defaults ⇒ Object
Constructor Details
#initialize(attrs = {}) ⇒ Request
First gets defaults from self.defaults, merges them with defaults from yaml_defaults
, merges all that with passed in attrs, and initializes all those into instance variables for use in to_xml.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/consumer/request.rb', line 127 def initialize(attrs = {}) # it's really handy to have all the other attrs init'd when we call # self.defaults 'cuz we can use them to help define conditional defaults. root = self.config_root yaml = Helper.hash_from_yaml(root, *yaml_defaults) yaml, attrs = symbolize_keys(yaml, attrs) initialize_attrs(yaml.merge(attrs)) # load yaml, but attrs will overwrite dups # now self.defaults has access to above stuff class_defaults = self.defaults class_defaults = symbolize_keys(class_defaults).first # but we wanted defaults loaded first. all_defaults = class_defaults.merge(yaml) final_attrs = all_defaults.merge(attrs) initialize_attrs(final_attrs) end |
Instance Attribute Details
#request_xml ⇒ Object (readonly)
Returns the value of attribute request_xml.
122 123 124 |
# File 'lib/consumer/request.rb', line 122 def request_xml @request_xml end |
#response_xml ⇒ Object (readonly)
Returns the value of attribute response_xml.
122 123 124 |
# File 'lib/consumer/request.rb', line 122 def response_xml @response_xml end |
Class Method Details
.basic_authentication(*args) ⇒ Object
73 74 75 |
# File 'lib/consumer/request.rb', line 73 def basic_authentication(*args) @request_user, @request_pass = args if !args.empty? end |
.defaults(defaults = nil) ⇒ Object
108 109 110 111 |
# File 'lib/consumer/request.rb', line 108 def defaults(defaults = nil) @defaults = defaults if defaults @defaults || {} end |
.do(args = {}) ⇒ Object
187 188 189 |
# File 'lib/consumer/request.rb', line 187 def self.do(args = {}) self.new(args).do end |
.error_paths(options = nil) ⇒ Object
113 114 115 116 |
# File 'lib/consumer/request.rb', line 113 def error_paths( = nil) @error_paths = if @error_paths end |
.request_pass(pass = nil) ⇒ Object
82 83 84 85 |
# File 'lib/consumer/request.rb', line 82 def request_pass(pass = nil) @request_pass = pass if pass @request_pass end |
.request_user(user = nil) ⇒ Object
77 78 79 80 |
# File 'lib/consumer/request.rb', line 77 def request_user(user = nil) @request_user = user if user @request_user end |
.required(*args) ⇒ Object
92 93 94 95 |
# File 'lib/consumer/request.rb', line 92 def required(*args) @required = args if !args.empty? @required || [] end |
.response_class(klass = nil) ⇒ Object
97 98 99 100 101 |
# File 'lib/consumer/request.rb', line 97 def response_class(klass = nil) @response_class = klass if klass self.to_s =~ /(.+?)Request/ @response_class || $1 end |
.url(url = nil) ⇒ Object
87 88 89 90 |
# File 'lib/consumer/request.rb', line 87 def url(url = nil) @url = url if url @url end |
.yaml_defaults(*args) ⇒ Object
103 104 105 106 |
# File 'lib/consumer/request.rb', line 103 def yaml_defaults(*args) @yaml_defaults = args if !args.empty? @yaml_defaults end |
Instance Method Details
#config_root ⇒ Object
245 246 247 248 249 250 251 |
# File 'lib/consumer/request.rb', line 245 def config_root if defined?(RAILS_ROOT) RAILS_ROOT + "/config" else "config" end end |
#defaults ⇒ Object
241 242 243 |
# File 'lib/consumer/request.rb', line 241 def defaults self.class.defaults end |
#do ⇒ Object
Sends self.to_xml to self.url and returns new object(s) created via [response_class].from_xml
Prerequisites
-
All attributes in self.required must exist; raises RequiredFieldError otherwise
-
self.to_xml must be defined; RuntimeError otherwise
-
self.url must be set; RuntimeError otherwise
-
response_class.from_xml must be defined; RuntimeError otherwise
Returns
Whatever response_class.from_xml(@response_xml) returns, which should be an object or array of objects (an array of objects if response_class is using Consumer::Mapping)
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/consumer/request.rb', line 158 def do return if defined?(self.abort?) && self.abort? raise "to_xml not defined for #{self.class}" if not defined?(self.to_xml) raise "url not defined for #{self.class}" if not self.url raise "from_xml not defined for #{response_class}" if not defined?(response_class.from_xml) @request_xml = self.to_xml_etc head = defined?(self.headers) ? self.headers : {} resp = nil uri = URI.parse self.url Net::HTTP.start(uri.host,uri.port) {|http| req = Net::HTTP::Get.new(uri.request_uri) req.basic_auth request_user, request_pass if request_user and request_pass req.body = @request_xml resp = http.request(req) } @response_xml = resp.body puts "\n##### Response:\n\n#{Helper.tidy(@response_xml)}\n" if $DEBUG check_request_error(@response_xml) return response_class.from_xml(@response_xml) end |
#error_paths ⇒ Object
225 226 227 |
# File 'lib/consumer/request.rb', line 225 def error_paths self.class.error_paths end |
#request_pass ⇒ Object
221 222 223 |
# File 'lib/consumer/request.rb', line 221 def request_pass self.class.request_pass end |
#request_user ⇒ Object
217 218 219 |
# File 'lib/consumer/request.rb', line 217 def request_user self.class.request_user end |
#required ⇒ Object
229 230 231 |
# File 'lib/consumer/request.rb', line 229 def required self.class.required end |
#response_class ⇒ Object
returns self.class.response_class as a constant (not a string)
Raises a runtime error if self.class.response_class is nil
211 212 213 214 215 |
# File 'lib/consumer/request.rb', line 211 def response_class ret = self.class.response_class raise "Invalid response_class; see docs for naming conventions etc" if !ret return Object.const_get(ret) end |
#to_xml_etc ⇒ Object
Gets called during do instead of just to_xml, and does a bit more than just return xml.
First, it calls before_to_xml if it has been defined. Then it calls check_required, then returns the results of to_xml sans empty nodes (see Helper.compact_xml).
You can set a COMPACT_XML constant to false to avoid the latter behavior, but most APIs complain when you send them empty nodes (even if the nodes were optional to begin with).
201 202 203 204 205 206 |
# File 'lib/consumer/request.rb', line 201 def to_xml_etc self.before_to_xml if defined?(before_to_xml) self.check_required xml = self.to_xml return (defined?(COMPACT_XML) && !COMPACT_XML) ? xml : Helper.compact_xml(xml) end |
#url ⇒ Object
237 238 239 |
# File 'lib/consumer/request.rb', line 237 def url self.class.url end |
#yaml_defaults ⇒ Object
233 234 235 |
# File 'lib/consumer/request.rb', line 233 def yaml_defaults self.class.yaml_defaults end |