diff options
Diffstat (limited to 'activerecord/lib')
4 files changed, 17 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index fbcb21118d..9ac561b997 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -31,7 +31,7 @@ module ActiveRecord::Associations::Builder end def belongs_to_counter_cache_before_destroy_for_#{name} - unless marked_for_destruction? + unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == #{foreign_key.to_sym.inspect} record = #{name} record.class.decrement_counter(:#{cache_column}, record.id) unless record.nil? end diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index b7b4d7e3ae..29fae809da 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -22,7 +22,7 @@ module ActiveRecord else if options[:dependent] == :destroy # No point in executing the counter update since we're going to destroy the parent anyway - load_target.each(&:mark_for_destruction) + load_target.each { |t| t.destroyed_by_association = reflection } destroy_all else delete_all diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 55542262b0..0df3e57947 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -212,6 +212,7 @@ module ActiveRecord # Reloads the attributes of the object as usual and clears <tt>marked_for_destruction</tt> flag. def reload(options = nil) @marked_for_destruction = false + @destroyed_by_association = nil super end @@ -231,6 +232,19 @@ module ActiveRecord @marked_for_destruction end + # Records the association that is being destroyed and destroying this + # record in the process. + def destroyed_by_association=(reflection) + @destroyed_by_association = reflection + end + + # Returns the association for the parent being destroyed. + # + # Used to avoid updating the counter cache unnecessarily. + def destroyed_by_association + @destroyed_by_association + end + # Returns whether or not this record has been changed in any way (including whether # any of its nested autosave associations are likewise changed) def changed_for_autosave? diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index aa56219755..968dad5844 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -427,6 +427,7 @@ module ActiveRecord @readonly = false @destroyed = false @marked_for_destruction = false + @destroyed_by_association = nil @new_record = true @txn = nil @_start_transaction_state = {} |