Speed up init with a refactor #37

Closed
wants to merge 3 commits into
from
@@ -39,9 +39,9 @@ def nearby_class(name) # {{{
# @private
def sibling_class(name) # {{{
if mod = self.containing_module
- "#{mod.name}::#{name}".constantize rescue nil
- else
- name.constantize rescue nil
+ @sibling_class ||= {}
+ @sibling_class[mod] ||= {}
+ @sibling_class[mod][name] ||= "#{mod.name}::#{name}".constantize rescue nil
end
end # }}}
View
@@ -7,18 +7,16 @@ module ORM
# Initialize a new object with data received from an HTTP request
# @private
- def initialize(data={}) # {{{
+ def initialize(params={}) # {{{
@data = {}
- @metadata = data.delete(:_metadata) || {}
- @errors = data.delete(:_errors) || {}
-
- # Only keep the keys that don't have corresponding writer methods
- cleaned_data = data.inject({}) do |memo, item|
- key, value = item
- send "#{key}=".to_sym, value unless value.nil?
- writer_method_defined?(key) ? memo : memo.merge({ key => value })
- end
- @data.merge! self.class.parse_relationships(cleaned_data)
+ @metadata = params.delete(:_metadata) || {}
+ @errors = params.delete(:_errors) || {}
+
+ # Use setter methods first, then translate attributes of relationships
+ # into relationship instances, then merge the parsed_data into @data.
+ unset_data = Her::Model::ORM.use_setter_methods(self, params)
+ parsed_data = self.class.parse_relationships(unset_data)
+ @data.update(parsed_data)
end # }}}
# Initialize a collection of resources
@@ -28,6 +26,21 @@ def self.initialize_collection(klass, parsed_data={}) # {{{
Her::Collection.new(collection_data, parsed_data[:metadata], parsed_data[:errors])
end # }}}
+ # Use setter methods of model for each key / value pair in params
+ # Return key / value pairs for which no setter method was defined on the model
+ def self.use_setter_methods(model, params) # {{{
+ setter_method_names = model.class.setter_method_names
+ params.inject({}) do |memo, (key, value)|
+ setter_method = key.to_s + '='
+ if setter_method_names.include?(setter_method)
+ model.send(setter_method, value)
+ else
+ memo[key] = value
+ end
+ memo
+ end
+ end # }}}
+
# Handles missing methods by routing them through @data
# @private
def method_missing(method, *args, &blk) # {{{
@@ -146,14 +159,6 @@ def to_params # {{{
@data.dup
end # }}}
- private
-
- # @private
- def writer_method_defined?(key) # {{{
- self.class.instance_methods.include?("#{key}=".to_sym) || # Ruby 1.9
- self.class.instance_methods.include?("#{key}=") # Ruby 1.8
- end # }}}
-
module ClassMethods
# Initialize a collection of resources with raw data from an HTTP request
#
@@ -236,6 +241,13 @@ def destroy_existing(id, params={}) # {{{
new(parsed_data[:data])
end
end # }}}
+
+ def setter_method_names
+ @setter_method_names ||= instance_methods.inject(Set.new) do |memo, method_name|
+ memo << method_name.to_s if method_name.to_s.end_with?('=')
+ memo
+ end
+ end
end
end
end
@@ -21,8 +21,8 @@ def parse_relationships(data) # {{{
relationships.each_pair do |type, definitions|
definitions.each do |relationship|
name = relationship[:name]
+ next unless data[name]
klass = self.nearby_class(relationship[:class_name])
- next if !data.include?(name) or data[name].nil?
data[name] = case type
when :has_many
Her::Model::ORM.initialize_collection(klass, :data => data[name])