Class: HyperResource
- Inherits:
-
Object
- Object
- HyperResource
- Includes:
- Enumerable, Modules::HTTP, Modules::InternalAttributes
- Defined in:
- lib/hyper_resource.rb,
lib/hyper_resource/links.rb,
lib/hyper_resource/adapter.rb,
lib/hyper_resource/objects.rb,
lib/hyper_resource/version.rb,
lib/hyper_resource/attributes.rb,
lib/hyper_resource/exceptions.rb,
lib/hyper_resource/modules/http.rb,
lib/hyper_resource/adapter/hal_json.rb
Overview
HyperResource is the main resource base class. Normally it will be used through subclassing, though it may also be used directly.
Defined Under Namespace
Modules: Modules Classes: Adapter, Attributes, ClientError, Exception, Link, Links, Objects, Response, ResponseError, ServerError
Constant Summary collapse
- VERSION =
'0.2.3'- VERSION_DATE =
'2014-03-12'
Class Method Summary collapse
-
.get_data_type_from_response(response) ⇒ Object
Inspects the given Faraday::Response, and returns a string describing this resource’s data type.
-
.response_class(response, namespace) ⇒ Object
Returns the class into which the given response should be cast.
Instance Method Summary collapse
-
#[](i) ⇒ Object
Returns the *i*th object in the first collection of objects embedded in this resource.
-
#_hr_new_from_link(href) ⇒ Object
Return a new HyperResource based on this object and a given href.
- #_hr_response_class ⇒ Object
-
#changed?(*args) ⇒ Boolean
Returns true if one or more of this object’s attributes has been reassigned.
- #deserialized_response ⇒ Object
-
#each(&block) ⇒ Object
Iterates over the objects in the first collection of embedded objects in this resource.
-
#get_data_type_from_response ⇒ Object
Uses
HyperResource.get_response_data_typeto determine the proper data type for this object. -
#incoming_body_filter(attr_hash) ⇒ Object
incoming_body_filterfilters a hash of attribute keys and values on their way from a response body to a HyperResource. -
#initialize(opts = {}) ⇒ HyperResource
constructor
Create a new HyperResource, given a hash of options.
- #inspect ⇒ Object
-
#method_missing(method, *args) ⇒ Object
method_missing will load this resource if not yet loaded, then attempt to delegate to
attributes, thenobjects, thenlinks. -
#outgoing_body_filter(attr_hash) ⇒ Object
outgoing_body_filterfilters a hash of attribute keys and values on their way from a HyperResource to a request body. -
#outgoing_uri_filter(attr_hash) ⇒ Object
outgoing_uri_filterfilters a hash of attribute keys and values on their way from a HyperResource to a URL. -
#response_body ⇒ Object
response_body,response_object, anddeserialized_responseare deprecated in favor ofbody. - #response_object ⇒ Object
Methods included from Modules::InternalAttributes
Methods included from Modules::HTTP
#create, #delete, #faraday_connection, #get, #patch, #post, #put, #update
Constructor Details
#initialize(opts = {}) ⇒ HyperResource
Create a new HyperResource, given a hash of options. These options include:
- root
-
The root URL of the resource.
- auth
-
Authentication information. Currently only {basic: [‘key’, ‘secret’]} is supported.
- namespace
-
Class or class name, into which resources should be instantiated.
- headers
-
Headers to send along with requests for this resource (as well as its eventual child resources, if any).
- faraday_options
-
Configuration passed to
Faraday::Connection.initialize, such as {request: {timeout: 30}}.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/hyper_resource.rb', line 51 def initialize(opts={}) return init_from_resource(opts) if opts.kind_of?(HyperResource) self.root = opts[:root] || self.class.root self.href = opts[:href] || '' self.auth = (self.class.auth || {}).merge(opts[:auth] || {}) self.namespace = opts[:namespace] || self.class.namespace self.headers = DEFAULT_HEADERS.merge(self.class.headers || {}). merge(opts[:headers] || {}) self. = opts[:faraday_options] || self.class. || {} ## There's a little acrobatics in getting Attributes, Links, and Objects ## into the correct subclass. if self.class != HyperResource if self.class::Attributes == HyperResource::Attributes Object.module_eval( "class #{self.class}::Attributes < HyperResource::Attributes; end" ) end if self.class::Links == HyperResource::Links Object.module_eval( "class #{self.class}::Links < HyperResource::Links; end" ) end if self.class::Objects == HyperResource::Objects Object.module_eval( "class #{self.class}::Objects < HyperResource::Objects; end" ) end end self.attributes = self.class::Attributes.new(self) self.links = self.class::Links.new(self) self.objects = self.class::Objects.new(self) self.loaded = false self.adapter = opts[:adapter] || self.class.adapter || HyperResource::Adapter::HAL_JSON end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ Object
method_missing will load this resource if not yet loaded, then attempt to delegate to attributes, then objects, then links. Override with care.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/hyper_resource.rb', line 147 def method_missing(method, *args) self.get unless self.loaded method = method.to_s if method[-1,1] == '=' return attributes[method[0..-2]] = args.first if attributes[method[0..-2]] else return attributes[method] if attributes && attributes[method] return objects[method] if objects && objects[method] if links && links[method] if args.count > 0 return links[method].where(*args) else return links[method] end end end raise NoMethodError, "undefined method `#{method}' for #{self.inspect}" end |
Class Method Details
.get_data_type_from_response(response) ⇒ Object
Inspects the given Faraday::Response, and returns a string describing this resource’s data type.
By default, this method looks for a type=… modifier in the response’s Content-type and returns that value, capitalized.
Override this method in a subclass to alter HyperResource’s behavior.
258 259 260 261 262 263 |
# File 'lib/hyper_resource.rb', line 258 def self.get_data_type_from_response(response) return nil unless response return nil unless content_type = response['content-type'] return nil unless m=content_type.match(/;\s* type=([0-9A-Za-z:]+)/x) m[1][0,1].upcase + m[1][1..-1] end |
.response_class(response, namespace) ⇒ Object
Returns the class into which the given response should be cast. If the object is not loaded yet, or if namespace is not set, returns self.
Otherwise, response_class uses get_data_type_from_response to determine subclass name, glues it to the given namespace, and creates the class if it’s not there yet. E.g., given a namespace of FooAPI and a response content-type of “application/vnd.foocorp.fooapi.v1+json;type=User”, this should return FooAPI::User (even if FooAPI::User hadn’t existed yet).
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/hyper_resource.rb', line 216 def self.response_class(response, namespace) if self.to_s == 'HyperResource' return self unless namespace end namespace ||= self.to_s type_name = self.get_data_type_from_response(response) return self unless type_name class_name = "#{namespace}::#{type_name}" class_name.gsub!(/[^_0-9A-Za-z:]/, '') ## sanitize class_name ## Return data type class if it exists klass = eval(class_name) rescue :sorry_dude return klass if klass.is_a?(Class) ## Data type class didn't exist -- create namespace (if necessary), ## then the data type class if namespace != '' nsc = eval(namespace) rescue :bzzzzzt unless nsc.is_a?(Class) Object.module_eval "class #{namespace} < #{self}; end" end end Object.module_eval "class #{class_name} < #{namespace}; end" eval(class_name) end |
Instance Method Details
#[](i) ⇒ Object
Returns the *i*th object in the first collection of objects embedded in this resource. Returns nil on failure.
130 131 132 133 |
# File 'lib/hyper_resource.rb', line 130 def [](i) get unless loaded self.objects.first[1][i] rescue nil end |
#_hr_new_from_link(href) ⇒ Object
Return a new HyperResource based on this object and a given href.
196 197 198 199 200 201 202 203 |
# File 'lib/hyper_resource.rb', line 196 def _hr_new_from_link(href) # @private self.class.new(:root => self.root, :auth => self.auth, :headers => self.headers, :namespace => self.namespace, :faraday_options => self., :href => href) end |
#_hr_response_class ⇒ Object
245 246 247 248 |
# File 'lib/hyper_resource.rb', line 245 def _hr_response_class # @private self.namespace ||= self.class.to_s unless self.class.to_s=='HyperResource' self.class.response_class(self.response, self.namespace) end |
#changed?(*args) ⇒ Boolean
Returns true if one or more of this object’s attributes has been reassigned.
96 97 98 |
# File 'lib/hyper_resource.rb', line 96 def changed?(*args) attributes.changed?(*args) end |
#deserialized_response ⇒ Object
187 188 189 190 191 |
# File 'lib/hyper_resource.rb', line 187 def deserialized_response # @private _hr_deprecate('HyperResource#deserialized_response is deprecated. '+ 'Please use HyperResource#body instead.') body end |
#each(&block) ⇒ Object
Iterates over the objects in the first collection of embedded objects in this resource.
137 138 139 140 |
# File 'lib/hyper_resource.rb', line 137 def each(&block) get unless loaded self.objects.first[1].each(&block) rescue nil end |
#get_data_type_from_response ⇒ Object
Uses HyperResource.get_response_data_type to determine the proper data type for this object. Override to change behavior (though you probably just want to override the class method).
268 269 270 |
# File 'lib/hyper_resource.rb', line 268 def get_data_type_from_response self.class.get_data_type_from_response(self.response) end |
#incoming_body_filter(attr_hash) ⇒ Object
incoming_body_filter filters a hash of attribute keys and values on their way from a response body to a HyperResource. Override this in a subclass of HyperResource to implement filters on incoming data.
106 107 108 |
# File 'lib/hyper_resource.rb', line 106 def incoming_body_filter(attr_hash) attr_hash end |
#inspect ⇒ Object
169 170 171 172 173 |
# File 'lib/hyper_resource.rb', line 169 def inspect # @private "#<#{self.class}:0x#{"%x" % self.object_id} @root=#{self.root.inspect} "+ "@href=#{self.href.inspect} @loaded=#{self.loaded} "+ "@namespace=#{self.namespace.inspect} ...>" end |
#outgoing_body_filter(attr_hash) ⇒ Object
outgoing_body_filter filters a hash of attribute keys and values on their way from a HyperResource to a request body. Override this in a subclass of HyperResource to implement filters on outgoing data.
113 114 115 |
# File 'lib/hyper_resource.rb', line 113 def outgoing_body_filter(attr_hash) attr_hash end |
#outgoing_uri_filter(attr_hash) ⇒ Object
outgoing_uri_filter filters a hash of attribute keys and values on their way from a HyperResource to a URL. Override this in a subclass of HyperResource to implement filters on outgoing URI parameters.
121 122 123 |
# File 'lib/hyper_resource.rb', line 121 def outgoing_uri_filter(attr_hash) attr_hash end |
#response_body ⇒ Object
response_body, response_object, and deserialized_response
are deprecated in favor of +body+. (Sorry. Naming things is hard.)
177 178 179 180 181 |
# File 'lib/hyper_resource.rb', line 177 def response_body # @private _hr_deprecate('HyperResource#response_body is deprecated. '+ 'Please use HyperResource#body instead.') body end |
#response_object ⇒ Object
182 183 184 185 186 |
# File 'lib/hyper_resource.rb', line 182 def response_object # @private _hr_deprecate('HyperResource#response_object is deprecated. '+ 'Please use HyperResource#body instead.') body end |