class HyperResource
HyperResource
is the main resource base class. Normally it will be used through subclassing, though it may also be used directly.
Constants
- DEFAULT_HEADERS
- VERSION
- VERSION_DATE
Public Class Methods
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.
# File lib/hyper_resource.rb, line 257 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
# File lib/hyper_resource.rb, line 225 def self.namespaced_class(type_name, namespace) 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
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).
# File lib/hyper_resource.rb, line 49 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] || {}) ## 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
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).
# File lib/hyper_resource.rb, line 212 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 namespaced_class(type_name, namespace) end
Private Class Methods
Show a deprecation message.
# File lib/hyper_resource.rb, line 290 def self._hr_deprecate(message) # @private STDERR.puts "#{message} (called from #{caller[2]})" end
Public Instance Methods
Returns the *i*th object in the first collection of objects embedded in this resource. Returns nil on failure.
# File lib/hyper_resource.rb, line 126 def [](i) get unless loaded self.objects.first[1][i] end
Return a new HyperResource
based on this object and a given href.
# File lib/hyper_resource.rb, line 192 def _hr_new_from_link(href) # @private self.class.new(:root => self.root, :auth => self.auth, :headers => self.headers, :namespace => self.namespace, :token => self.token, :href => href) end
# 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
Returns true if one or more of this object's attributes has been reassigned.
# File lib/hyper_resource.rb, line 92 def changed?(*args) attributes.changed?(*args) end
# File lib/hyper_resource.rb, line 183 def deserialized_response # @private _hr_deprecate('HyperResource#deserialized_response is deprecated. '+ 'Please use HyperResource#body instead.') body end
Iterates over the objects in the first collection of embedded objects in this resource.
# File lib/hyper_resource.rb, line 133 def each(&block) get unless loaded self.objects.first[1].each(&block) end
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).
# File lib/hyper_resource.rb, line 267 def get_data_type_from_response self.class.get_data_type_from_response(self.response) end
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.
# File lib/hyper_resource.rb, line 102 def incoming_body_filter(attr_hash) attr_hash end
# File lib/hyper_resource.rb, line 165 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
method_missing
will load this resource if not yet loaded, then attempt to delegate to attributes
, then objects
, then links
. Override with care.
# File lib/hyper_resource.rb, line 143 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.has_key?(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
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.
# File lib/hyper_resource.rb, line 109 def outgoing_body_filter(attr_hash) attr_hash end
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.
# File lib/hyper_resource.rb, line 117 def outgoing_uri_filter(attr_hash) attr_hash end
response_body
, response_object
, and deserialized_response
are deprecated in favor of +body+. (Sorry. Naming things is hard.)
# File lib/hyper_resource.rb, line 173 def response_body # @private _hr_deprecate('HyperResource#response_body is deprecated. '+ 'Please use HyperResource#body instead.') body end
# File lib/hyper_resource.rb, line 178 def response_object # @private _hr_deprecate('HyperResource#response_object is deprecated. '+ 'Please use HyperResource#body instead.') body end
Private Instance Methods
# File lib/hyper_resource.rb, line 294 def _hr_deprecate(*args) # @private self.class._hr_deprecate(*args) end
Use the given resource's data to initialize this one.
# File lib/hyper_resource.rb, line 281 def init_from_resource(resource) (self.class._hr_attributes - [:attributes, :links, :objects]).each do |attr| self.send("#{attr}=".to_sym, resource.send(attr)) end self.adapter.apply(self.body, self) end
Return this object, “cast” into its proper response class.
# File lib/hyper_resource.rb, line 274 def to_response_class response_class = self._hr_response_class return self if self.class == response_class response_class.new(self) end