mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Fix: Inconsistent Polymorphic Association Autosave
This commit is contained in:
parent
e6d4ac0e50
commit
589321d99a
5 changed files with 58 additions and 1 deletions
|
@ -463,7 +463,8 @@ module ActiveRecord
|
|||
# If the record is new or it has changed, returns true.
|
||||
def _record_changed?(reflection, record, key)
|
||||
record.new_record? ||
|
||||
association_foreign_key_changed?(reflection, record, key) ||
|
||||
(association_foreign_key_changed?(reflection, record, key) ||
|
||||
inverse_polymorphic_association_changed?(reflection, record)) ||
|
||||
record.will_save_change_to_attribute?(reflection.foreign_key)
|
||||
end
|
||||
|
||||
|
@ -473,6 +474,14 @@ module ActiveRecord
|
|||
record._has_attribute?(reflection.foreign_key) && record._read_attribute(reflection.foreign_key) != key
|
||||
end
|
||||
|
||||
def inverse_polymorphic_association_changed?(reflection, record)
|
||||
return false unless reflection.inverse_of&.polymorphic?
|
||||
|
||||
class_name = record._read_attribute(reflection.inverse_of.foreign_type)
|
||||
|
||||
reflection.active_record != record.class.polymorphic_class_for(class_name)
|
||||
end
|
||||
|
||||
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
||||
#
|
||||
# In addition, it will destroy the association if it was marked for destruction.
|
||||
|
|
|
@ -36,6 +36,9 @@ require "models/tuning_peg"
|
|||
require "models/reply"
|
||||
require "models/attachment"
|
||||
require "models/translation"
|
||||
require "models/chef"
|
||||
require "models/cake_designer"
|
||||
require "models/drink_designer"
|
||||
|
||||
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
|
||||
def test_autosave_works_even_when_other_callbacks_update_the_parent_model
|
||||
|
@ -1276,6 +1279,8 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
||||
fixtures :chefs, :cake_designers, :drink_designers
|
||||
|
||||
self.use_transactional_tests = false unless supports_savepoints?
|
||||
|
||||
def setup
|
||||
|
@ -1416,6 +1421,34 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
|||
|
||||
assert_not_predicate ship, :valid?
|
||||
end
|
||||
|
||||
def test_recognises_inverse_polymorphic_association_changes_with_same_foreign_key
|
||||
chef_a = chefs(:gordon_ramsay)
|
||||
chef_b = chefs(:marco_pierre_white)
|
||||
|
||||
cake_designer_a = cake_designers(:flora) # id: 1
|
||||
cake_designer_a.update!(chef: chef_a)
|
||||
cake_designer_b = cake_designers(:frosty) # id: 3
|
||||
cake_designer_b.update!(chef: chef_b)
|
||||
|
||||
drink_designer_a = drink_designers(:turner) # id: 1
|
||||
drink_designer_b = drink_designers(:sparrow) # id: 2
|
||||
|
||||
swap_chefs(cake_designer_b, drink_designer_b)
|
||||
assert_predicate cake_designer_b.reload.chef, :present?
|
||||
assert_not_predicate drink_designer_b.reload.chef, :present?
|
||||
|
||||
swap_chefs(cake_designer_a, drink_designer_a)
|
||||
assert_predicate cake_designer_a.reload.chef, :present?
|
||||
assert_not_predicate drink_designer_a.reload.chef, :present?
|
||||
end
|
||||
|
||||
private
|
||||
def swap_chefs(cake_designer, drink_designer)
|
||||
drink_designer.chef = cake_designer.chef
|
||||
drink_designer.save!
|
||||
cake_designer.save!
|
||||
end
|
||||
end
|
||||
|
||||
class TestAutosaveAssociationOnAHasOneThroughAssociation < ActiveRecord::TestCase
|
||||
|
|
5
activerecord/test/fixtures/cake_designers.yml
vendored
Normal file
5
activerecord/test/fixtures/cake_designers.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
flora:
|
||||
id: 1
|
||||
|
||||
frosty:
|
||||
id: 2
|
5
activerecord/test/fixtures/chefs.yml
vendored
Normal file
5
activerecord/test/fixtures/chefs.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
gordon_ramsay:
|
||||
id: 1
|
||||
|
||||
marco_pierre_white:
|
||||
id: 2
|
5
activerecord/test/fixtures/drink_designers.yml
vendored
Normal file
5
activerecord/test/fixtures/drink_designers.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
turner:
|
||||
id: 1
|
||||
|
||||
sparrow:
|
||||
id: 3
|
Loading…
Reference in a new issue