diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index a43ebdf60d..45341765c1 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -177,6 +177,11 @@ module ActiveRecord affected_rows = super + if @_skip_dirty_tracking ||= false + clear_attribute_changes(@_touch_attr_names) + return affected_rows + end + changes = {} @attributes.keys.each do |attr_name| next if @_touch_attr_names.include?(attr_name) @@ -193,7 +198,7 @@ module ActiveRecord affected_rows ensure - @_touch_attr_names = nil + @_touch_attr_names, @_skip_dirty_tracking = nil, nil end def _update_record(attribute_names = attribute_names_for_partial_writes) diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb index 6872b7844e..bc63c8d987 100644 --- a/activerecord/lib/active_record/touch_later.rb +++ b/activerecord/lib/active_record/touch_later.rb @@ -44,6 +44,7 @@ module ActiveRecord def touch_deferred_attributes if has_defer_touch_attrs? && persisted? + @_skip_dirty_tracking = true touch(*@_defer_touch_attrs, time: @_touch_time) @_defer_touch_attrs, @_touch_time = nil, nil end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 32285f269a..9869657961 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -2711,18 +2711,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase bulb = Bulb.create! tyre = Tyre.create! - car = Car.create! do |c| + car = Car.create!(name: "honda") do |c| c.bulbs << bulb c.tyres << tyre end + assert_equal [nil, "honda"], car.saved_change_to_name + assert_equal 1, car.bulbs.count assert_equal 1, car.tyres.count end test "associations replace in memory when records have the same id" do bulb = Bulb.create! - car = Car.create!(bulbs: [bulb]) + car = Car.create!(name: "honda", bulbs: [bulb]) + + assert_equal [nil, "honda"], car.saved_change_to_name new_bulb = Bulb.find(bulb.id) new_bulb.name = "foo" @@ -2733,7 +2737,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase test "in memory replacement executes no queries" do bulb = Bulb.create! - car = Car.create!(bulbs: [bulb]) + car = Car.create!(name: "honda", bulbs: [bulb]) + + assert_equal [nil, "honda"], car.saved_change_to_name new_bulb = Bulb.find(bulb.id) @@ -2765,7 +2771,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase test "in memory replacements sets inverse instance" do bulb = Bulb.create! - car = Car.create!(bulbs: [bulb]) + car = Car.create!(name: "honda", bulbs: [bulb]) + + assert_equal [nil, "honda"], car.saved_change_to_name new_bulb = Bulb.find(bulb.id) car.bulbs = [new_bulb] @@ -2785,7 +2793,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase test "in memory replacement maintains order" do first_bulb = Bulb.create! second_bulb = Bulb.create! - car = Car.create!(bulbs: [first_bulb, second_bulb]) + car = Car.create!(name: "honda", bulbs: [first_bulb, second_bulb]) + + assert_equal [nil, "honda"], car.saved_change_to_name same_bulb = Bulb.find(first_bulb.id) car.bulbs = [second_bulb, same_bulb]