hyperresource 0.2.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,159 @@
1
+ require 'uri'
2
+ require 'fuzzyurl'
3
+
4
+ class HyperResource
5
+
6
+ ## HyperResource::Configuration is a class which implements a hostmask-
7
+ ## scoped set of configurations. Key/value pairs are stored under hostmasks
8
+ ## like 'api.example.com:8080', 'api.example.com', '*.example.com', or '*'.
9
+ ## Values are retrieved using a hostname and a key, preferring more specific
10
+ ## hostmasks when more than one matching hostmask and key are present.
11
+ ##
12
+ ## HyperResource users are not expected to use this class directly.
13
+ class Configuration
14
+
15
+ ## Creates a new HyperResource::Configuration, with the given initial
16
+ ## internal state if provided.
17
+ def initialize(cfg={})
18
+ @cfg = cfg
19
+ @cfg['*'] ||= {}
20
+ end
21
+
22
+ ## Returns a deep copy of this object.
23
+ def clone
24
+ self.class.new.send(:initialize_copy, self)
25
+ end
26
+
27
+ ## Merges a given Configuration with this one. Deep-merges config
28
+ ## attributes correctly.
29
+ def merge(new)
30
+ merged_cfg = {}
31
+ new_cfg = new.send(:cfg)
32
+
33
+ (new_cfg.keys | cfg.keys).each do |mask|
34
+ new_cfg_attrs = new_cfg[mask] || {}
35
+ cfg_attrs = cfg[mask] || {}
36
+ merged_cfg[mask] = {}
37
+
38
+ ## Do a hash merge when it makes sense, except when it doesn't.
39
+ (new_cfg_attrs.keys | cfg_attrs.keys).each do |attr|
40
+ if !(%w(namespace adapter).include?(attr)) &&
41
+ ((!cfg_attrs[attr] || cfg_attrs[attr].kind_of?(Hash)) &&
42
+ (!new_cfg_attrs[attr] || new_cfg_attrs[attr].kind_of?(Hash)))
43
+ merged_cfg[mask][attr] =
44
+ (cfg_attrs[attr] || {}).merge(new_cfg_attrs[attr] || {})
45
+ else
46
+ merged_cfg[mask][attr] = new_cfg_attrs[attr] || cfg_attrs[attr]
47
+ end
48
+ end
49
+ end
50
+ self.class.new(merged_cfg)
51
+ end
52
+
53
+ ## Applies a given Configuration on top of this one.
54
+ def merge!(new)
55
+ initialize_copy(merge(new))
56
+ end
57
+
58
+ ## Applies a given Hash of configurations on top of this one.
59
+ def config(hash)
60
+ merge!(self.class.new(hash))
61
+ end
62
+
63
+ ## Returns this object as a Hash.
64
+ def as_hash
65
+ clone.send(:cfg)
66
+ end
67
+
68
+ ## Returns the value for a particular hostmask and key, or nil if not
69
+ ## present.
70
+ def get(mask, key)
71
+ cfg[mask] ||= {}
72
+ cfg[mask][key.to_s]
73
+ end
74
+
75
+ ## Sets a key and value pair for the given hostmask.
76
+ def set(mask, key, value)
77
+ cfg[mask] ||= {}
78
+ cfg[mask][key.to_s] = value
79
+ end
80
+
81
+ ## Returns the best matching value for the given URL and key, or nil
82
+ ## otherwise.
83
+ def get_for_url(url, key)
84
+ subconfig_for_url(url)[key.to_s]
85
+ end
86
+
87
+ ## Sets a key and value pair, using the given URL as the basis of the
88
+ ## hostmask. Path, query, and fragment are ignored.
89
+ def set_for_url(url, key, value)
90
+ furl = FuzzyURL.new(url || '*')
91
+ furl.path = nil
92
+ furl.query = nil
93
+ furl.fragment = nil
94
+ set(furl.to_s, key, value)
95
+ end
96
+
97
+
98
+ ## Returns hostmasks from our config which match the given url.
99
+ def matching_masks_for_url(url)
100
+ url = url.to_s
101
+ return ['*'] if !url || cfg.keys.count == 1
102
+ @masks ||= {} ## key = mask string, value = FuzzyURL
103
+ cfg.keys.each {|key| @masks[key] ||= FuzzyURL.new(key) }
104
+
105
+ ## Test for matches, and sort by score.
106
+ scores = {}
107
+ cfg.keys.each {|key| scores[key] = @masks[key].match(url) }
108
+ scores = Hash[ scores.select{|k,v| v} ] # remove nils
109
+ scores.keys.sort_by{|k| [-scores[k], -k.length]} ## TODO length is cheesy
110
+ end
111
+
112
+ private
113
+
114
+ def cfg
115
+ @cfg
116
+ end
117
+
118
+ ## Performs a two-level-deep copy of old @cfg.
119
+ def initialize_copy(old)
120
+ old.send(:cfg).each do |mask, old_subcfg|
121
+ new_subcfg = {}
122
+ old_subcfg.each do |key, value|
123
+ if value.kind_of?(Array) || value.kind_of?(Hash)
124
+ value = value.clone
125
+ end
126
+ new_subcfg[key] = value
127
+ end
128
+ @cfg[mask] = new_subcfg
129
+ end
130
+ self
131
+ end
132
+
133
+
134
+ ## Returns a merged subconfig consisting of all matching hostmask
135
+ ## subconfigs, giving priority to more specific hostmasks.
136
+ def subconfig_for_url(url)
137
+ matching_masks_for_url(url).inject({}) do |subcfg, mask|
138
+ (cfg[mask] || {}).merge(subcfg)
139
+ end
140
+ end
141
+
142
+ ## Returns the hostmasks which match the given url, sorted best match
143
+ ## first.
144
+ def get_possible_masks_for_host(host, port=80, masks=nil)
145
+ masks ||= ["#{host}:#{port}", host] ## exact matches first
146
+ host_parts = host.split('.')
147
+
148
+ if host_parts.count < 2
149
+ masks << '*' ## wildcard match last
150
+ else
151
+ parent_domain = host_parts[1..-1].join('.')
152
+ masks << '*.' + parent_domain
153
+ get_possible_masks_for_host(parent_domain, port, masks)
154
+ end
155
+ end
156
+
157
+ end
158
+ end
159
+
@@ -3,7 +3,8 @@ class HyperResource
3
3
  ## The internal exception which led to this one, if any.
4
4
  attr_accessor :cause
5
5
 
6
- def initialize(message, attrs={}) # @private
6
+ # @private
7
+ def initialize(message, attrs={})
7
8
  self.cause = attrs[:cause]
8
9
  super(message)
9
10
  end
@@ -17,7 +18,8 @@ class HyperResource
17
18
  ## May be blank, e.g. in case of deserialization errors.
18
19
  attr_accessor :body
19
20
 
20
- def initialize(message, attrs={}) # @private
21
+ # @private
22
+ def initialize(message, attrs={})
21
23
  self.response = attrs[:response]
22
24
  self.body = attrs[:body]
23
25
 
@@ -1,59 +1,100 @@
1
1
  require 'uri_template'
2
+ require 'hyper_resource/modules/http'
2
3
 
3
- class HyperResource::Link
4
- attr_accessor :base_href,
5
- :name,
6
- :templated,
7
- :params,
8
- :parent_resource
9
-
10
- ## Returns true if this link is templated.
11
- def templated?; templated end
12
-
13
- def initialize(resource=nil, link_spec={})
14
- self.parent_resource = resource || HyperResource.new
15
- self.base_href = link_spec['href']
16
- self.name = link_spec['name']
17
- self.templated = !!link_spec['templated']
18
- self.params = link_spec['params'] || {}
19
- end
4
+ class HyperResource
5
+
6
+ ## HyperResource::Link is an object to represent a hyperlink and its
7
+ ## URL or body parameters, and to encapsulate HTTP calls involving this
8
+ ## link. Links are typically created by HyperResource, not by end users.
9
+ ##
10
+ ## HTTP method calls return the response as a HyperResource (or subclass)
11
+ ## object. Calling an unrecognized method on a link will automatically
12
+ ## load the resource pointed to by this link, and repeat the method call
13
+ ## on the resource object.
14
+ ##
15
+ ## A HyperResource::Link requires the resource it is based upon to remain
16
+ ## in scope. In practice this is rarely a problem, as links are almost
17
+ ## always accessed through the resource object.
18
+
19
+ class Link
20
+
21
+ include HyperResource::Modules::HTTP
22
+
23
+ ## The literal href of this link; may be templated.
24
+ attr_accessor :base_href
25
+
26
+ ## An optional name describing this link.
27
+ attr_accessor :name
28
+
29
+ ## `true` if this link's href is a URI Template, `false` otherwise.
30
+ attr_accessor :templated
31
+
32
+ ## A hash of URL or request body parameters.
33
+ attr_accessor :params
34
+
35
+ ## Default HTTP method for implicit loading.
36
+ attr_accessor :default_method
37
+
38
+ ## The resource from which this link originates.
39
+ attr_accessor :resource
40
+
41
+ ## Returns a link based on the given resource and link specification
42
+ ## hash. `link_spec` keys are: `href` (string, required), `templated`
43
+ ## (boolean), `params` (hash), and `default_method` (string, default
44
+ ## `"get"`).
45
+ def initialize(resource, link_spec={})
46
+ unless link_spec.kind_of?(Hash)
47
+ raise ArgumentError, "link_spec must be a Hash (got #{link_spec.inspect})"
48
+ end
49
+ link_spec = Hash[ link_spec.map{|(k,v)| [k.to_s, v]} ] ## stringify keys
20
50
 
21
- ## Returns this link's href, applying any URI template params.
22
- def href
23
- if self.templated?
24
- filtered_params = self.parent_resource.outgoing_uri_filter(params)
25
- URITemplate.new(self.base_href).expand(filtered_params)
26
- else
27
- self.base_href
51
+ self.resource = resource
52
+ self.base_href = link_spec['href']
53
+ self.name = link_spec['name']
54
+ self.templated = !!link_spec['templated']
55
+ self.params = link_spec['params'] || {}
56
+ self.default_method = link_spec['method'] || 'get'
28
57
  end
29
- end
30
58
 
31
- ## Returns a new scope with the given params; that is, returns a copy of
32
- ## itself with the given params applied.
33
- def where(params)
34
- params = Hash[ params.map{|(k,v)| [k.to_s, v]} ]
35
- self.class.new(self.parent_resource,
36
- 'href' => self.base_href,
37
- 'name' => self.name,
38
- 'templated' => self.templated,
39
- 'params' => self.params.merge(params))
40
- end
59
+ ## Returns this link's href, applying any URI template params.
60
+ def href
61
+ if self.templated
62
+ filtered_params = self.resource.outgoing_uri_filter(params)
63
+ URITemplate.new(self.base_href).expand(filtered_params)
64
+ else
65
+ self.base_href
66
+ end
67
+ end
41
68
 
42
- ## Returns a HyperResource representing this link
43
- def resource
44
- parent_resource._hr_new_from_link(self.href)
45
- end
69
+ ## Returns this link's fully resolved URL, or nil if `resource.root`
70
+ ## or `href` are malformed.
71
+ def url
72
+ begin
73
+ URI.join(self.resource.root, self.href.to_s).to_s
74
+ rescue StandardError
75
+ nil
76
+ end
77
+ end
78
+
79
+ ## Returns a new scope with the given params; that is, returns a copy of
80
+ ## itself with the given params applied.
81
+ def where(params)
82
+ params = Hash[ params.map{|(k,v)| [k.to_s, v]} ]
83
+ self.class.new(self.resource,
84
+ 'href' => self.base_href,
85
+ 'name' => self.name,
86
+ 'templated' => self.templated,
87
+ 'params' => self.params.merge(params),
88
+ 'method' => self.default_method)
89
+ end
90
+
91
+ ## Unrecognized methods invoke an implicit load of the resource pointed
92
+ ## to by this link. The method call is then repeated on the returned
93
+ ## resource.
94
+ def method_missing(method, *args)
95
+ self.send(default_method || :get).send(method, *args)
96
+ end
46
97
 
47
- ## Delegate HTTP methods to the resource.
48
- def get(*args); self.resource.get(*args) end
49
- def post(*args); self.resource.post(*args) end
50
- def patch(*args); self.resource.patch(*args) end
51
- def put(*args); self.resource.put(*args) end
52
- def delete(*args); self.resource.delete(*args) end
53
-
54
- ## If we were called with a method we don't know, load this resource
55
- ## and pass the message along. This achieves implicit loading.
56
- def method_missing(method, *args)
57
- self.get.send(method, *args)
58
98
  end
59
99
  end
100
+
@@ -1,52 +1,53 @@
1
1
  class HyperResource
2
+
3
+ ## HyperResource::Links is a modified Hash that permits lookup
4
+ ## of a link by its link relation (rel), or an abbreviation thereof.
5
+ ## It also provides read access through `method_missing`.
6
+ ## It is typically created by HyperResource, not by end users.
7
+ ##
8
+ ## For example, a link with rel `someapi:widgets` is accessible
9
+ ## by any of `self.widgets`, `self['widgets']`, `self[:widgets]`, and
10
+ ## `self['someapi:widgets'].
2
11
  class Links < Hash
3
- attr_accessor :_resource
4
12
 
13
+ # @private
5
14
  def initialize(resource=nil)
6
- self._resource = resource || HyperResource.new
15
+ ## We used to store the resource, but we didn't need to. Now we don't.
7
16
  end
8
17
 
9
- ## Creates accessor methods in self.class and self._resource.class.
10
- ## Protects against method creation into HyperResource::Links and
11
- ## HyperResource classes. Just subclasses, please!
12
- def _hr_create_methods!(opts={}) # @private
13
- return if self.class.to_s == 'HyperResource::Links'
14
- return if self._resource.class.to_s == 'HyperResource'
15
- return if self.class.send(
16
- :class_variable_defined?, :@@_hr_created_links_methods)
17
-
18
- self.keys.each do |attr|
19
- attr_sym = attr.to_sym
20
- self.class.send(:define_method, attr_sym) do |*args|
21
- if args.count > 0
22
- self[attr].where(*args)
23
- else
24
- self[attr]
25
- end
26
- end
27
-
28
- ## Don't stomp on _resource's methods
29
- unless _resource.respond_to?(attr_sym)
30
- _resource.class.send(:define_method, attr_sym) do |*args|
31
- links.send(attr_sym, *args)
32
- end
33
- end
18
+ ## Stores a link for future retrieval by its link rel or abbreviations
19
+ ## thereof.
20
+ def []=(rel, link)
21
+ rel = rel.to_s
22
+
23
+ ## Every link must appear under its literal name.
24
+ names = [rel]
25
+
26
+ ## Extract 'foo' from e.g. 'http://example.com/foo',
27
+ ## 'http://example.com/url#foo', 'somecurie:foo'.
28
+ if m=rel.match(%r{[:/#](.+)})
29
+ names << m[1]
34
30
  end
35
31
 
36
- self.class.send(:class_variable_set, :@@_hr_created_links_methods, true)
37
- end
32
+ ## Underscore all non-word characters.
33
+ underscored_names = names.map{|n| n.gsub(/[^a-zA-Z_]/, '_')}
34
+ names = (names + underscored_names).uniq
38
35
 
39
- def []=(attr, value) # @private
40
- super(attr.to_s, value)
36
+ ## Register this link under every name we've come up with.
37
+ names.each do |name|
38
+ super(name, link)
39
+ end
41
40
  end
42
41
 
43
- def [](key) # @private
44
- return super(key.to_s) if self.has_key?(key.to_s)
45
- return super(key.to_sym) if self.has_key?(key.to_sym)
46
- nil
42
+ ## Retrieves a link by its rel.
43
+ def [](rel)
44
+ super(rel.to_s)
47
45
  end
48
46
 
49
- def method_missing(method, *args) # @private
47
+ ## Provides links.somelink(:a => b) to links.somelink.where(:a => b)
48
+ ## expansion.
49
+ # @private
50
+ def method_missing(method, *args)
50
51
  unless self[method]
51
52
  raise NoMethodError, "undefined method `#{method}' for #{self.inspect}"
52
53
  end
@@ -58,6 +59,11 @@ class HyperResource
58
59
  end
59
60
  end
60
61
 
62
+ # @private
63
+ def respond_to?(method, *args)
64
+ return true if self.has_key?(method.to_s)
65
+ super
66
+ end
61
67
  end
62
68
  end
63
69
 
@@ -0,0 +1,293 @@
1
+ class HyperResource
2
+ module Modules
3
+ module ConfigAttributes
4
+
5
+ ATTRS = [:auth, :headers, :namespace, :adapter, :faraday_options]
6
+
7
+ def self.included(klass)
8
+ klass.extend(ClassMethods)
9
+ end
10
+
11
+ # @private
12
+ def hr_config
13
+ @hr_config ||= self.class::Configuration.new
14
+ end
15
+
16
+ # @private
17
+ def hr_config=(cfg)
18
+ @hr_config = cfg
19
+ end
20
+
21
+ ## When called with no arguments, returns this resource's Configuration.
22
+ ## When called with a hash, applies the given configuration parameters
23
+ ## to this resource's Configuration. `hash` must be in the form:
24
+ ## {'hostmask' => {'attr1' => {...}, 'attr2' => {...}, ...}}
25
+ ## Valid attributes are `auth`, `headers`, `namespace`, `adapter`,
26
+ ## `default_attributes`, and `faraday_options`.
27
+ def config(hash=nil)
28
+ return hr_config unless hash
29
+ hr_config.config(hash)
30
+ end
31
+
32
+
33
+ ## Returns the auth config hash for this resource.
34
+ def auth
35
+ cfg_get(:auth)
36
+ end
37
+
38
+ ## Returns the auth config hash for the given url.
39
+ def auth_for_url(url)
40
+ self.hr_config.get_for_url(url, :auth)
41
+ end
42
+
43
+ ## Sets the auth config hash for this resource.
44
+ ## Currently only the format `{:basic => ['username', 'password']}`
45
+ ## is supported.
46
+ def auth=(v)
47
+ cfg_set(:auth, v)
48
+ end
49
+
50
+
51
+ ## Returns the headers hash for this resource.
52
+ ## This is done by merging all applicable header configs.
53
+ def headers
54
+ matching_masks = self.hr_config.matching_masks_for_url(self.url)
55
+ matching_masks.inject({}) do |hash, mask|
56
+ hash.merge(self.hr_config.get(mask, 'headers') || {})
57
+ end
58
+ end
59
+
60
+ ## Returns the headers hash for the given url.
61
+ def headers_for_url(url)
62
+ self.hr_config.get_for_url(url, :headers)
63
+ end
64
+
65
+ ## Sets the headers hash for this resource.
66
+ def headers=(v)
67
+ cfg_set(:headers, v)
68
+ end
69
+
70
+
71
+ ## Returns the namespace string/class for this resource.
72
+ def namespace
73
+ cfg_get(:namespace)
74
+ end
75
+
76
+ ## Returns the namespace string/class for the given url.
77
+ def namespace_for_url(url)
78
+ self.hr_config.get_for_url(url, :namespace)
79
+ end
80
+
81
+ ## Sets the namespace string/class for this resource.
82
+ def namespace=(v)
83
+ cfg_set(:namespace, v)
84
+ end
85
+
86
+
87
+ ## Returns the adapter class for this resource.
88
+ def adapter
89
+ cfg_get(:adapter) ||
90
+ HyperResource::Adapter::HAL_JSON
91
+ end
92
+
93
+ ## Returns the adapter class for the given url.
94
+ def adapter_for_url(url)
95
+ self.hr_config.get_for_url(url, :adapter) ||
96
+ HyperResource::Adapter::HAL_JSON
97
+ end
98
+
99
+ ## Sets the adapter class for this resource.
100
+ def adapter=(v)
101
+ cfg_set(:adapter, v)
102
+ end
103
+
104
+
105
+ ## Returns the hash of default attributes for this resource.
106
+ def default_attributes
107
+ cfg_get(:default_attributes)
108
+ end
109
+
110
+ ## Returns the hash of default attributes for the given url.
111
+ def default_attributes_for_url(url)
112
+ self.hr_config.get_for_url(url, :default_attributes)
113
+ end
114
+
115
+ ## Sets the hash of default attributes for this resource.
116
+ ## These attributes will be passed along with every HTTP request.
117
+ def default_attributes=(v)
118
+ cfg_set(:default_attributes, v)
119
+ end
120
+
121
+
122
+ ## Returns the Faraday connection options hash for this resource.
123
+ def faraday_options
124
+ cfg_get(:faraday_options)
125
+ end
126
+
127
+ ## Returns the Faraday connection options hash for this resource.
128
+ def faraday_options_for_url(url)
129
+ self.hr_config.get_for_url(url, :faraday_options)
130
+ end
131
+
132
+ ## Sets the Faraday connection options hash for this resource.
133
+ ## These options will be used for all HTTP requests.
134
+ def faraday_options=(v)
135
+ cfg_set(:faraday_options, v)
136
+ end
137
+
138
+
139
+ private
140
+
141
+ def cfg_get(key)
142
+ hr_config.get_for_url(self.url, key) ||
143
+ self.class.hr_config.get_for_url(self.url, key)
144
+ end
145
+
146
+ ## Sets a config key-value pair for this resource.
147
+ def cfg_set(key, value)
148
+ hr_config.set_for_url(url.to_s, key, value)
149
+ end
150
+
151
+ public
152
+
153
+ module ClassMethods
154
+
155
+ def hr_config
156
+ @hr_config ||= self::Configuration.new
157
+ end
158
+
159
+ ## When called with no arguments, returns this class's Configuration.
160
+ ## When called with a hash, applies the given configuration parameters
161
+ ## to this resource's Configuration. `hash` must be in the form:
162
+ ## {'hostmask' => {'key1' => 'value1', 'key2' => 'value2', ...}}
163
+ ## Valid keys are `auth`, `headers`, `namespace`, `adapter`, and
164
+ ## `faraday_options`.
165
+ def config(hash=nil)
166
+ return hr_config unless hash
167
+ hr_config.config(hash)
168
+ end
169
+
170
+
171
+ ## Returns the auth config hash for this resource class.
172
+ def auth
173
+ cfg_get(:auth)
174
+ end
175
+
176
+ ## Returns the auth config hash for the given url.
177
+ def auth_for_url(url)
178
+ self.hr_config.get_for_url(url, :auth)
179
+ end
180
+
181
+ ## Sets the auth config hash for this resource class.
182
+ ## Currently only the format `{:basic => ['username', 'password']}`
183
+ ## is supported.
184
+ def auth=(v)
185
+ cfg_set(:auth, v)
186
+ end
187
+
188
+
189
+ ## Returns the headers hash for this resource class.
190
+ def headers
191
+ cfg_get(:headers)
192
+ end
193
+
194
+ ## Returns the headers hash for the given url.
195
+ def headers_for_url(url)
196
+ self.hr_config.get_for_url(url, :headers)
197
+ end
198
+
199
+ ## Sets the headers hash for this resource class.
200
+ def headers=(v)
201
+ cfg_set(:headers, v)
202
+ end
203
+
204
+
205
+ ## Returns the namespace string/class for this resource class.
206
+ def namespace
207
+ cfg_get(:namespace)
208
+ end
209
+
210
+ ## Returns the namespace string/class for the given url.
211
+ def namespace_for_url(url)
212
+ self.hr_config.get_for_url(url, :namespace)
213
+ end
214
+
215
+ ## Sets the namespace string/class for this resource class.
216
+ def namespace=(v)
217
+ cfg_set(:namespace, v)
218
+ end
219
+
220
+
221
+ ## Returns the adapter class for this resource class.
222
+ def adapter
223
+ cfg_get(:adapter) || HyperResource::Adapter::HAL_JSON
224
+ end
225
+
226
+ ## Returns the adapter class for the given url.
227
+ def adapter_for_url(url)
228
+ self.hr_config.get_for_url(url, :adapter) ||
229
+ HyperResource::Adapter::HAL_JSON
230
+ end
231
+
232
+ ## Sets the adapter class for this resource class.
233
+ def adapter=(v)
234
+ cfg_set(:adapter, v)
235
+ end
236
+
237
+
238
+ ## Returns the hash of default attributes for this resource class.
239
+ def default_attributes
240
+ cfg_get(:default_attributes)
241
+ end
242
+
243
+ ## Returns the hash of default attributes for the given url.
244
+ def default_attributes_for_url(url)
245
+ self.hr_config.get_for_url(url, :default_attributes)
246
+ end
247
+
248
+ ## Sets the hash of default attributes for this resource class.
249
+ ## These attributes will be passed along with every HTTP request.
250
+ def default_attributes=(v)
251
+ cfg_set(:default_attributes, v)
252
+ end
253
+
254
+
255
+ ## Returns the Faraday connection options hash for this resource class.
256
+ def faraday_options
257
+ cfg_get(:faraday_options)
258
+ end
259
+
260
+ ## Returns the Faraday connection options hash for this resource class.
261
+ def faraday_options_for_url(url)
262
+ self.hr_config.get_for_url(url, :faraday_options)
263
+ end
264
+
265
+ ## Sets the Faraday connection options hash for this resource class.
266
+ ## These options will be used for all HTTP requests.
267
+ def faraday_options=(v)
268
+ cfg_set(:faraday_options, v)
269
+ end
270
+
271
+
272
+ private
273
+
274
+ def cfg_get(key)
275
+ value = hr_config.get_for_url(self.root, key)
276
+ if value != nil
277
+ value
278
+ elsif superclass.respond_to?(:hr_config)
279
+ superclass.hr_config.get_for_url(self.root, key)
280
+ else
281
+ nil
282
+ end
283
+ end
284
+
285
+ def cfg_set(key, value)
286
+ hr_config.set_for_url(self.root, key, value)
287
+ end
288
+
289
+ end
290
+
291
+ end
292
+ end
293
+ end