lib/hyper_resource.rb in hyperresource-0.1.9.2 vs lib/hyper_resource.rb in hyperresource-0.1.9.3
- old
+ new
@@ -1,25 +1,10 @@
-require 'hyper_resource/version'
-require 'hyper_resource/attributes'
-require 'hyper_resource/links'
-require 'hyper_resource/link'
-require 'hyper_resource/objects'
-require 'hyper_resource/response'
-require 'hyper_resource/exceptions'
+this_dir = File.dirname(File.absolute_path(__FILE__))
+Dir.glob(this_dir + '/hyper_resource/**/*.rb') {|f| require f}
-require 'hyper_resource/modules/utils'
-require 'hyper_resource/modules/http'
-
-require 'hyper_resource/adapter'
-require 'hyper_resource/adapter/hal_json'
-
require 'pp'
-## TODO:
-## as_json, to_json (in adapter?)
-## save, update, create, delete
-
class HyperResource
include HyperResource::Modules::Utils
include HyperResource::Modules::HTTP
private
@@ -115,41 +100,19 @@
self.adapter = opts[:adapter] || self.class.adapter ||
HyperResource::Adapter::HAL_JSON
end
-private
- 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.response_object, self)
- end
-
public
+ ## Returns true if one or more of this object's attributes has been
+ ## reassigned.
def changed?(*args)
attributes.changed?(*args)
end
- ## Returns a new HyperResource based on the given link href.
- def _new_from_link(href)
- self.class.new(:root => self.root,
- :auth => self.auth,
- :headers => self.headers,
- :namespace => self.namespace,
- :href => href)
- end
-
- def to_response_class
- response_class = self.get_response_class
- return self if self.class == response_class
- response_class.new(self)
- 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.
def incoming_body_filter(attr_hash)
attr_hash
@@ -169,34 +132,87 @@
def outgoing_uri_filter(attr_hash)
attr_hash
end
- def get_response_class # :nodoc:
- self.namespace ||= self.class.to_s unless self.class.to_s=='HyperResource'
- self.class.get_response_class(self.response, self.namespace)
+ ## Returns the first object in the first collection of objects embedded
+ ## in this resource. Equivalent to +self.objects.first+.
+ def first; self.objects.first end
+
+ ## Returns the *i*th object in the first collection of objects embedded
+ ## in this resource. Equivalent to +self.objects[i]+.
+ def [](i); self.objects.ith(i) end
+
+ ## method_missing will load this resource if not yet loaded, then
+ ## attempt to delegate to +attributes+, then +objects+, then +links+.
+ ## Override with care.
+ def method_missing(method, *args)
+ self.get unless self.loaded
+
+ method = method.to_s
+ if method[-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
+
+ def inspect # :nodoc:
+ "#<#{self.class}:0x#{"%x" % self.object_id} @root=#{self.root.inspect} "+
+ "@href=#{self.href.inspect} @loaded=#{self.loaded} "+
+ "@namespace=#{self.namespace.inspect} ...>"
+ end
+
+ ## +response_body+ is deprecated in favor of +response_object+.
+ def response_body; response_object end # :nodoc:
+
+
+ #######################################################################
+ #### Underscored functions are not meant to be used outside of ####
+ #### HyperResource machinery. You have been warned. ####
+
+
+ ## Return a new HyperResource based on this object and a given href.
+ def _new_from_link(href) # :nodoc:
+ self.class.new(:root => self.root,
+ :auth => self.auth,
+ :headers => self.headers,
+ :namespace => self.namespace,
+ :href => href)
+ end
+
+
## Returns the class into which the given response should be cast.
## If the object is not loaded yet, or if +opts[:namespace]+ is
## not set, returns +self+.
##
- ## Otherwise, +get_response_class+ uses +get_response_data_type+ to
+ ## Otherwise, +_get_response_class+ uses +_get_response_data_type+ 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).
- def self.get_response_class(response, namespace)
+ def self._get_response_class(response, namespace) # :nodoc:
if self.to_s == 'HyperResource'
return self unless namespace
end
namespace ||= self.to_s
- type_name = self.get_response_data_type(response)
+ type_name = self._get_response_data_type(response)
return self unless type_name
class_name = "#{namespace}::#{type_name}"
class_name.gsub!(/[^_0-9A-Za-z:]/, '') ## sanitize class_name
@@ -214,63 +230,47 @@
end
Object.module_eval "class #{class_name} < #{namespace}; end"
eval(class_name)
end
-
- def get_response_data_type
- self.class.get_response_data_type(self.response)
+ def _get_response_class # :nodoc:
+ self.namespace ||= self.class.to_s unless self.class.to_s=='HyperResource'
+ self.class._get_response_class(self.response, self.namespace)
end
+
## Inspects the given 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.
- def self.get_response_data_type(response)
+ def self._get_response_data_type(response) # :nodoc:
return nil unless response
return nil unless content_type = response['content-type']
return nil unless m=content_type.match(/;\s* type=(?<type> [0-9A-Za-z:]+)/x)
m[:type][0].upcase + m[:type][1..-1]
end
-
-
- ## Returns the first object in the first collection of objects embedded
- ## in this resource. Equivalent to +self.objects.first+.
- def first; self.objects.first end
-
- ## Returns the *i*th object in the first collection of objects embedded
- ## in this resource. Equivalent to +self.objects[i]+.
- def [](i); self.objects.ith(i) end
-
- ## method_missing will load this resource if not yet loaded, then
- ## attempt to delegate to +attributes+, then +objects+, then +links+.
- def method_missing(method, *args)
- self.get unless self.loaded
-
- method = method.to_s
- if method[-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]
- return links[method] if links && links[method]
- end
-
- raise NoMethodError, "undefined method `#{method}' for #{self.inspect}"
+ def _get_response_data_type # :nodoc:
+ self.class._get_response_data_type(self.response)
end
+private
- def inspect # :nodoc:
- "#<#{self.class}:0x#{"%x" % self.object_id} @root=#{self.root.inspect} "+
- "@href=#{self.href.inspect} @loaded=#{self.loaded} "+
- "@namespace=#{self.namespace.inspect} ...>"
+ ## Return this object, "cast" into its proper response class.
+ def to_response_class # :nodoc:
+ response_class = self._get_response_class
+ return self if self.class == response_class
+ response_class.new(self)
end
- ## +response_body+ is deprecated in favor of +response_object+.
- def response_body; response_object end
+ 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.response_object, self)
+ end
end