lib/active_remote/association.rb in active_remote-1.7.1 vs lib/active_remote/association.rb in active_remote-1.8.0.rc1

- old
+ new

@@ -37,13 +37,16 @@ # end # end # def belongs_to(belongs_to_klass, options={}) perform_association(belongs_to_klass, options) do |klass, object| - foreign_key = options.fetch(:foreign_key) { :"#{belongs_to_klass}_guid" } - association_guid = object.read_attribute(foreign_key) - klass.search(:guid => association_guid).first if association_guid + foreign_key = options.fetch(:foreign_key) { :"#{klass.name.demodulize.underscore}_guid" } + search_hash = {} + search_hash[:guid] = object.read_attribute(foreign_key) + search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.has_key?(:scope) + + search_hash.values.any?(&:nil?) ? nil : klass.search(search_hash).first end end # Create a `has_many` association for a given remote resource. # Specify one or more associations to define. The constantized @@ -74,13 +77,17 @@ # User.search(:client_guid => self.guid) # end # end # def has_many(has_many_class, options={}) - perform_association( has_many_class, options ) do |klass, object| + perform_association(has_many_class, options) do |klass, object| foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" } - object.guid ? klass.search(foreign_key => object.guid) : [] + search_hash = {} + search_hash[foreign_key] = object.guid + search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.has_key?(:scope) + + search_hash.values.any?(&:nil?) ? [] : klass.search(search_hash) end end # Create a `has_one` association for a given remote resource. # Specify one or more associations to define. The constantized @@ -97,12 +104,10 @@ # # ====Examples # # class User # has_one :client - # end - # # An equivalent code snippet without a `has_one` declaration would be: # # ====Examples # # class User @@ -112,28 +117,44 @@ # end # def has_one(has_one_klass, options={}) perform_association(has_one_klass, options) do |klass, object| foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" } - klass.search(foreign_key => object.guid).first if object.guid + search_hash = {} + search_hash[foreign_key] = object.guid + search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.has_key?(:scope) + + search_hash.values.any?(&:nil?) ? nil : klass.search(search_hash).first end end + # when requiring an attribute on your search, we verify the attribute + # exists on both models + def validate_scoped_attributes(associated_class, object_class, options) + raise "Could not find attribute: '#{options[:scope]}' on #{object_class}" unless object_class.public_instance_methods.include?(options[:scope]) + raise "Could not find attribute: '#{options[:scope]}' on #{associated_class}" unless associated_class.public_instance_methods.include?(options[:scope]) + end + private - def perform_association(associated_klass, optionz={}) + def perform_association(associated_klass, options={}) + define_method(associated_klass) do + klass_name = options.fetch(:class_name){ associated_klass } + klass = klass_name.to_s.classify.constantize + + self.class.validate_scoped_attributes(klass, self.class, options) if options.has_key?(:scope) + value = instance_variable_get(:"@#{associated_klass}") unless value - klass_name = optionz.fetch(:class_name){ associated_klass } - klass = klass_name.to_s.classify.constantize value = yield( klass, self ) instance_variable_set(:"@#{associated_klass}", value) end return value end end + end end end