From 97c4dd34dc0d9e3a4e10ca22e546061983bb125a Mon Sep 17 00:00:00 2001 From: David J. Hamilton Date: Fri, 16 Jul 2010 16:45:48 -0700 Subject: [PATCH] Patch for 5137. association accessor for :through associations failed to set association when :through a belongs_to association. --- activerecord/lib/active_record/associations.rb | 15 +++++++++++---- .../associations/belongs_to_associations_test.rb | 10 ++++++++++ .../has_one_through_associations_test.rb | 12 ++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index f2feac0..3247044 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1449,11 +1449,18 @@ module ActiveRecord if association.nil? || force_reload association = association_proxy_class.new(self, reflection) retval = force_reload ? reflection.klass.uncached { association.reload } : association.reload - if retval.nil? and association_proxy_class == BelongsToAssociation - association_instance_set(reflection.name, nil) - return nil - end association_instance_set(reflection.name, association) + elsif reflection.belongs_to? && self.class.column_names.include?(reflection.primary_key_name) + key = read_attribute(reflection.primary_key_name) + target_primary_key = + if association.target + association.target.send( reflection.options[:primary_key] || 'id' ) + end + + # If A belongs_to B, we reload the association whenever A's key + # differs from A.B.id, e.g. because the user invoked A.key= or + # A.B= + association.reload if key != target_primary_key end association.target.nil? ? nil : association diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 7425132..3685717 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -313,6 +313,16 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal Firm.find(:first, :order => "id"), c.firm_with_basic_id end + def test_forgetting_the_load_when_foreign_key_changes + first_firm = companies(:first_firm) + another_firm = companies(:another_firm) + + c = Client.new({ :firm_id => first_firm.id }) + assert_equal c.firm_with_basic_id, first_firm + c.firm_id = another_firm.id + assert_equal c.firm_with_basic_id, another_firm + end + def test_field_name_same_as_foreign_key computer = Computer.find(1) assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # ' diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 5d15314..d095891 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -42,6 +42,18 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase assert_equal clubs(:moustache_club), new_member.club end + def test_creating_association_builds_through_record_for_new_through_belongs_to + new_minivan = Minivan.new + assert_nothing_raised do + new_minivan.dashboard = dashboards( :cool_first ) + end + assert new_minivan.speedometer + assert_equal dashboards( :cool_first ), new_minivan.speedometer.dashboard + assert_equal dashboards( :cool_first ), new_minivan.dashboard + assert new_minivan.save + assert_equal dashboards( :cool_first ), new_minivan.dashboard + end + def test_replace_target_record new_club = Club.create(:name => "Marx Bros") @member.club = new_club -- 1.7.2