From 939b896a06c0cff661076d0ca3fbe8c1d5552e83 Mon Sep 17 00:00:00 2001 From: larrylv Date: Mon, 4 Mar 2013 17:38:22 +0800 Subject: Fix issue #7526. Reload the target if it's stale. * This has been fixed at master via `365b8b6`, but not at 3-2-stable branch. * @stale_state should be nil when a model isn't saved. via `0f3901e`. * set @stale_state to nil when reset the target. --- activerecord/CHANGELOG.md | 6 ++++++ activerecord/lib/active_record/associations/association.rb | 7 ++++--- .../active_record/associations/belongs_to_association.rb | 2 +- .../associations/belongs_to_polymorphic_association.rb | 3 ++- .../lib/active_record/associations/through_association.rb | 2 +- .../cases/associations/belongs_to_associations_test.rb | 14 ++++++++++++++ 6 files changed, 28 insertions(+), 6 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 519d3f784f..ffc5b95296 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,11 @@ ## unreleased ## +* Reload the association target if it's stale. `@stale_state` should be nil + when a model isn't saved. + Fixes #7526. + + *Larry Lv* + * Don't read CSV files during execution of `db:fixtures:load`. CSV support for fixtures was removed some time ago but the task was still loading them, even though later the code was looking for the related yaml file instead. diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index ab0d888b16..861df46e3c 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -46,6 +46,7 @@ module ActiveRecord @loaded = false IdentityMap.remove(target) if IdentityMap.enabled? && target @target = nil + @stale_state = nil end # Reloads the \target and returns +self+ on success. @@ -134,15 +135,15 @@ module ActiveRecord # ActiveRecord::RecordNotFound is rescued within the method, and it is # not reraised. The proxy is \reset and +nil+ is the return value. def load_target - if find_target? + if (@stale_state && stale_target?) || find_target? begin if IdentityMap.enabled? && association_class && association_class.respond_to?(:base_class) @target = IdentityMap.get(association_class, owner[reflection.foreign_key]) + else + @target = find_target end rescue NameError nil - ensure - @target ||= find_target end end loaded! unless loaded? diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index 97f531d064..52c67df646 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -72,7 +72,7 @@ module ActiveRecord end def stale_state - owner[reflection.foreign_key].to_s + owner[reflection.foreign_key] && owner[reflection.foreign_key].to_s end end end diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb index 2ee5dbbd70..88ce03a3cd 100644 --- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -27,7 +27,8 @@ module ActiveRecord end def stale_state - [super, owner[reflection.foreign_type].to_s] + foreign_key = super + foreign_key && [foreign_key.to_s, owner[reflection.foreign_type].to_s] end end end diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index fd0e90aaf0..be890e5767 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -62,7 +62,7 @@ module ActiveRecord # properly support stale-checking for nested associations. def stale_state if through_reflection.macro == :belongs_to - owner[through_reflection.foreign_key].to_s + owner[through_reflection.foreign_key] && owner[through_reflection.foreign_key].to_s end end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index f392366c19..c9b26895ae 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -14,6 +14,8 @@ require 'models/sponsor' require 'models/member' require 'models/essay' require 'models/toy' +require 'models/person' +require 'models/reader' class BelongsToAssociationsTest < ActiveRecord::TestCase fixtures :accounts, :companies, :developers, :projects, :topics, @@ -716,4 +718,16 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal toy, sponsor.reload.sponsorable end + + def test_saving_nested_association + post1, post2 = Post.limit(2) + person = Person.new(:first_name => 'foo') + reader = Reader.new(:post => post1) + + reader.post_id = post2.id + person.readers = [reader] + + assert person.save + assert_equal reader.post_id, post2.id + end end -- cgit v1.2.3