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