[Fix #52332] Handle record changed case in #save_has_one_association's inverse belongs_to association updated check

This commit is contained in:
Joshua Young 2024-07-15 08:47:55 +05:30
parent f74dc0d8aa
commit 9920ad3ef4
2 changed files with 47 additions and 17 deletions

@ -436,9 +436,6 @@ def save_has_one_association(reflection)
record = association && association.load_target record = association && association.load_target
return unless record && !record.destroyed? return unless record && !record.destroyed?
inverse_belongs_to_association = inverse_belongs_to_association_for(reflection, record)
return if inverse_belongs_to_association && inverse_belongs_to_association.updated?
autosave = reflection.options[:autosave] autosave = reflection.options[:autosave]
if autosave && record.marked_for_destruction? if autosave && record.marked_for_destruction?
@ -447,7 +444,13 @@ def save_has_one_association(reflection)
primary_key = Array(compute_primary_key(reflection, self)).map(&:to_s) primary_key = Array(compute_primary_key(reflection, self)).map(&:to_s)
primary_key_value = primary_key.map { |key| _read_attribute(key) } primary_key_value = primary_key.map { |key| _read_attribute(key) }
if (autosave && record.changed_for_autosave?) || _record_changed?(reflection, record, primary_key_value) return unless (autosave && record.changed_for_autosave?) || (record_changed = _record_changed?(reflection, record, primary_key_value))
unless record_changed
inverse_belongs_to_association = inverse_belongs_to_association_for(reflection, record)
return if inverse_belongs_to_association && inverse_belongs_to_association.updated?
end
unless reflection.through_reflection unless reflection.through_reflection
foreign_key = Array(reflection.foreign_key) foreign_key = Array(reflection.foreign_key)
primary_key_foreign_key_pairs = primary_key.zip(foreign_key) primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
@ -464,7 +467,6 @@ def save_has_one_association(reflection)
saved saved
end end
end end
end
def inverse_belongs_to_association_for(reflection, record) def inverse_belongs_to_association_for(reflection, record)
!reflection.belongs_to? && !reflection.belongs_to? &&

@ -314,6 +314,17 @@ def test_callbacks_on_child_when_parent_autosaves_child
assert_equal 1, eye.iris.after_save_callbacks_counter assert_equal 1, eye.iris.after_save_callbacks_counter
end end
def test_callbacks_on_child_when_parent_autosaves_child_twice
eye = Eye.create!(iris: Iris.new)
eye.update!(iris: Iris.new)
assert_equal 1, eye.iris.before_validation_callbacks_counter
assert_equal 1, eye.iris.before_create_callbacks_counter
assert_equal 1, eye.iris.before_save_callbacks_counter
assert_equal 1, eye.iris.after_validation_callbacks_counter
assert_equal 1, eye.iris.after_create_callbacks_counter
assert_equal 1, eye.iris.after_save_callbacks_counter
end
def test_callbacks_on_child_when_parent_autosaves_polymorphic_child_with_inverse_of def test_callbacks_on_child_when_parent_autosaves_polymorphic_child_with_inverse_of
drink_designer = DrinkDesigner.create!(chef: ChefWithPolymorphicInverseOf.new) drink_designer = DrinkDesigner.create!(chef: ChefWithPolymorphicInverseOf.new)
assert_equal 1, drink_designer.chef.before_validation_callbacks_counter assert_equal 1, drink_designer.chef.before_validation_callbacks_counter
@ -334,6 +345,17 @@ def test_callbacks_on_child_when_child_autosaves_parent
assert_equal 1, iris.after_save_callbacks_counter assert_equal 1, iris.after_save_callbacks_counter
end end
def test_callbacks_on_child_when_child_autosaves_parent_twice
iris = Iris.create!(eye: Eye.new)
iris.update!(eye: Eye.new)
assert_equal 2, iris.before_validation_callbacks_counter
assert_equal 1, iris.before_create_callbacks_counter
assert_equal 2, iris.before_save_callbacks_counter
assert_equal 2, iris.after_validation_callbacks_counter
assert_equal 1, iris.after_create_callbacks_counter
assert_equal 2, iris.after_save_callbacks_counter
end
def test_callbacks_on_child_when_polymorphic_child_with_inverse_of_autosaves_parent def test_callbacks_on_child_when_polymorphic_child_with_inverse_of_autosaves_parent
chef = ChefWithPolymorphicInverseOf.create!(employable: DrinkDesigner.new) chef = ChefWithPolymorphicInverseOf.create!(employable: DrinkDesigner.new)
assert_equal 1, chef.before_validation_callbacks_counter assert_equal 1, chef.before_validation_callbacks_counter
@ -1812,6 +1834,12 @@ def test_should_save_with_non_nullable_foreign_keys
child.save! child.save!
assert_equal child.reload.post, parent.reload assert_equal child.reload.post, parent.reload
end end
def test_should_save_if_previously_saved
ship = Ship.create(name: "Nights Dirty Lightning", pirate: Pirate.new(catchphrase: "Arrrr"))
ship.create_pirate(catchphrase: "Savvy?")
assert_equal "Savvy?", ship.reload.pirate.catchphrase
end
end end
module AutosaveAssociationOnACollectionAssociationTests module AutosaveAssociationOnACollectionAssociationTests