Skip to content

Commit

Permalink
Refactor we_can_set_the_inverse_on_this? to use a less bizarre name a…
Browse files Browse the repository at this point in the history
…mongst other things
  • Loading branch information
jonleighton authored and tenderlove committed Dec 26, 2010
1 parent 57420df commit 9f5c18c
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 52 deletions.
5 changes: 2 additions & 3 deletions activerecord/lib/active_record/association_preload.rb
Expand Up @@ -127,8 +127,7 @@ def add_preloaded_records_to_collection(parent_records, reflection_name, associa
association_proxy = parent_record.send(reflection_name) association_proxy = parent_record.send(reflection_name)
association_proxy.loaded association_proxy.loaded
association_proxy.target.push(*Array.wrap(associated_record)) association_proxy.target.push(*Array.wrap(associated_record))

association_proxy.send(:set_inverse_instance, associated_record)
association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
end end
end end


Expand Down Expand Up @@ -157,7 +156,7 @@ def set_association_single_records(id_to_record_map, reflection_name, associated
mapped_records = id_to_record_map[associated_record[key].to_s] mapped_records = id_to_record_map[associated_record[key].to_s]
mapped_records.each do |mapped_record| mapped_records.each do |mapped_record|
association_proxy = mapped_record.send("set_#{reflection_name}_target", associated_record) association_proxy = mapped_record.send("set_#{reflection_name}_target", associated_record)
association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record) association_proxy.send(:set_inverse_instance, associated_record)
end end
end end


Expand Down
Expand Up @@ -454,9 +454,7 @@ def find_target
end end


records = @reflection.options[:uniq] ? uniq(records) : records records = @reflection.options[:uniq] ? uniq(records) : records
records.each do |record| records.each { |record| set_inverse_instance(record) }
set_inverse_instance(record, @owner)
end
records records
end end


Expand All @@ -470,7 +468,7 @@ def add_record_to_target_with_callbacks(record)
@target << record @target << record
end end
callback(:after_add, record) callback(:after_add, record)
set_inverse_instance(record, @owner) set_inverse_instance(record)
record record
end end


Expand Down
24 changes: 15 additions & 9 deletions activerecord/lib/active_record/associations/association_proxy.rb
Expand Up @@ -217,6 +217,13 @@ def aliased_table
@reflection.klass.arel_table @reflection.klass.arel_table
end end


# Set the inverse association, if possible
def set_inverse_instance(record)
if record && invertible_for?(record)
record.send("set_#{inverse_reflection_for(record).name}_target", @owner)
end
end

private private
# Forwards any missing method call to the \target. # Forwards any missing method call to the \target.
def method_missing(method, *args) def method_missing(method, *args)
Expand Down Expand Up @@ -280,17 +287,16 @@ def owner_quoted_id
@owner.quoted_id @owner.quoted_id
end end


def set_inverse_instance(record, instance) # Can be redefined by subclasses, notably polymorphic belongs_to
return if record.nil? || !we_can_set_the_inverse_on_this?(record) # The record parameter is necessary to support polymorphic inverses as we must check for
inverse_relationship = @reflection.inverse_of # the association in the specific class of the record.
unless inverse_relationship.nil? def inverse_reflection_for(record)
record.send(:"set_#{inverse_relationship.name}_target", instance) @reflection.inverse_of
end
end end


# Override in subclasses # Is this association invertible? Can be redefined by subclasses.
def we_can_set_the_inverse_on_this?(record) def invertible_for?(record)
false inverse_reflection_for(record)
end end
end end
end end
Expand Down
Expand Up @@ -32,7 +32,7 @@ def replace(record)
@updated = true @updated = true
end end


set_inverse_instance(record, @owner) set_inverse_instance(record)


loaded loaded
record record
Expand Down Expand Up @@ -69,7 +69,7 @@ def find_target
options options
) if @owner[@reflection.primary_key_name] ) if @owner[@reflection.primary_key_name]
end end
set_inverse_instance(the_target, @owner) set_inverse_instance(the_target)
the_target the_target
end end


Expand All @@ -83,8 +83,9 @@ def foreign_key_present


# NOTE - for now, we're only supporting inverse setting from belongs_to back onto # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
# has_one associations. # has_one associations.
def we_can_set_the_inverse_on_this?(record) def invertible_for?(record)
@reflection.has_inverse? && @reflection.inverse_of.macro == :has_one inverse = inverse_reflection_for(record)
inverse && inverse.macro == :has_one
end end


def record_id(record) def record_id(record)
Expand Down
Expand Up @@ -14,7 +14,7 @@ def replace(record)
@updated = true @updated = true
end end


set_inverse_instance(record, @owner) set_inverse_instance(record)
loaded loaded
record record
end end
Expand All @@ -38,23 +38,13 @@ def stale_target?


private private


# NOTE - for now, we're only supporting inverse setting from belongs_to back onto def inverse_reflection_for(record)
# has_one associations. @reflection.polymorphic_inverse_of(record.class)
def we_can_set_the_inverse_on_this?(record)
if @reflection.has_inverse?
inverse_association = @reflection.polymorphic_inverse_of(record.class)
inverse_association && inverse_association.macro == :has_one
else
false
end
end end


def set_inverse_instance(record, instance) def invertible_for?(record)
return if record.nil? || !we_can_set_the_inverse_on_this?(record) inverse = inverse_reflection_for(record)
inverse_relationship = @reflection.polymorphic_inverse_of(record.class) inverse && inverse.macro == :has_one
if inverse_relationship
record.send(:"set_#{inverse_relationship.name}_target", instance)
end
end end


def construct_find_scope def construct_find_scope
Expand All @@ -71,7 +61,7 @@ def find_target
:include => @reflection.options[:include] :include => @reflection.options[:include]
) )
end end
set_inverse_instance(target, @owner) set_inverse_instance(target)
target target
end end


Expand Down
Expand Up @@ -212,7 +212,7 @@ def construct_association(record, join_part, row)
collection = record.send(join_part.reflection.name) collection = record.send(join_part.reflection.name)
collection.loaded collection.loaded
collection.target.push(association) collection.target.push(association)
collection.__send__(:set_inverse_instance, association, record) collection.send(:set_inverse_instance, association)
when :belongs_to when :belongs_to
set_target_and_inverse(join_part, association, record) set_target_and_inverse(join_part, association, record)
else else
Expand All @@ -224,7 +224,7 @@ def construct_association(record, join_part, row)


def set_target_and_inverse(join_part, association, record) def set_target_and_inverse(join_part, association, record)
association_proxy = record.send("set_#{join_part.reflection.name}_target", association) association_proxy = record.send("set_#{join_part.reflection.name}_target", association)
association_proxy.__send__(:set_inverse_instance, association, record) association_proxy.send(:set_inverse_instance, association)
end end
end end
end end
Expand Down
Expand Up @@ -110,6 +110,10 @@ def record_timestamp_columns(record)
[] []
end end
end end

def invertible_for?(record)
false
end
end end
end end
end end
Expand Up @@ -92,10 +92,6 @@ def construct_find_scope
def construct_create_scope def construct_create_scope
construct_owner_attributes construct_owner_attributes
end end

def we_can_set_the_inverse_on_this?(record)
@reflection.inverse_of
end
end end
end end
end end
Expand Up @@ -67,7 +67,7 @@ def find_target
end end


# NOTE - not sure that we can actually cope with inverses here # NOTE - not sure that we can actually cope with inverses here
def we_can_set_the_inverse_on_this?(record) def invertible_for?(record)
false false
end end
end end
Expand Down
Expand Up @@ -55,7 +55,7 @@ def replace(obj, dont_save = false)
@target = (AssociationProxy === obj ? obj.target : obj) @target = (AssociationProxy === obj ? obj.target : obj)
end end


set_inverse_instance(obj, @owner) set_inverse_instance(obj)
@loaded = true @loaded = true


unless !@owner.persisted? || obj.nil? || dont_save unless !@owner.persisted? || obj.nil? || dont_save
Expand All @@ -81,7 +81,7 @@ def find_target
the_target = with_scope(:find => @scope[:find]) do the_target = with_scope(:find => @scope[:find]) do
@reflection.klass.find(:first, options) @reflection.klass.find(:first, options)
end end
set_inverse_instance(the_target, @owner) set_inverse_instance(the_target)
the_target the_target
end end


Expand All @@ -107,17 +107,12 @@ def new_record(replace_existing)
else else
record[@reflection.primary_key_name] = @owner.id if @owner.persisted? record[@reflection.primary_key_name] = @owner.id if @owner.persisted?
self.target = record self.target = record
set_inverse_instance(record, @owner) set_inverse_instance(record)
end end


record record
end end


def we_can_set_the_inverse_on_this?(record)
inverse = @reflection.inverse_of
return !inverse.nil?
end

def merge_with_conditions(attrs={}) def merge_with_conditions(attrs={})
attrs ||= {} attrs ||= {}
attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash) attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
Expand Down

0 comments on commit 9f5c18c

Please sign in to comment.