From 1c07b84df95e932d50376c1d0a13585b2e2ef868 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 23 Dec 2010 13:36:25 +0000 Subject: If a has_many goes :through a belongs_to, and the foreign key of the belongs_to changes, then the has_many should be considered stale. --- .../associations/belongs_to_association.rb | 5 ++++- .../belongs_to_polymorphic_association.rb | 8 ++++++-- .../associations/has_many_through_association.rb | 1 + .../associations/has_one_through_association.rb | 1 + .../associations/through_association_scope.rb | 19 +++++++++++++++++++ 5 files changed, 31 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record/associations') diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index c9abfe36e8..bbfe18f9fb 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -44,7 +44,10 @@ module ActiveRecord def stale_target? if @target && @target.persisted? - @target.send(@reflection.association_primary_key).to_i != @owner.send(@reflection.primary_key_name).to_i + target_id = @target.send(@reflection.association_primary_key).to_s + foreign_key = @owner.send(@reflection.primary_key_name).to_s + + target_id != foreign_key else false 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 844ae94c3d..c580de7fbe 100644 --- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -25,8 +25,12 @@ module ActiveRecord def stale_target? if @target && @target.persisted? - @target.send(@reflection.association_primary_key).to_i != @owner.send(@reflection.primary_key_name).to_i || - @target.class.base_class.name.to_s != @owner.send(@reflection.options[:foreign_type]).to_s + target_id = @target.send(@reflection.association_primary_key).to_s + foreign_key = @owner.send(@reflection.primary_key_name).to_s + target_type = @target.class.base_class.name + foreign_type = @owner.send(@reflection.options[:foreign_type]).to_s + + target_id != foreign_key || target_type != foreign_type else false end diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index f0bc6aedf2..5f4667b4d8 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -59,6 +59,7 @@ module ActiveRecord def find_target return [] unless target_reflection_has_associated_record? + update_stale_state scoped.all end diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index e8cf73976b..eb17935d6a 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -33,6 +33,7 @@ module ActiveRecord private def find_target + update_stale_state scoped.first end end diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index c11fce5db0..e57de84f66 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -10,6 +10,17 @@ module ActiveRecord end end + def stale_target? + if @target && @reflection.through_reflection.macro == :belongs_to && defined?(@through_foreign_key) + previous_key = @through_foreign_key.to_s + current_key = @owner.send(@reflection.through_reflection.primary_key_name).to_s + + previous_key != current_key + else + false + end + end + protected def construct_find_scope @@ -165,6 +176,14 @@ module ActiveRecord end alias_method :sql_conditions, :conditions + + def update_stale_state + construct_scope if stale_target? + + if @reflection.through_reflection.macro == :belongs_to + @through_foreign_key = @owner.send(@reflection.through_reflection.primary_key_name) + end + end end end end -- cgit v1.2.3