Skip to content

Commit 20a0e51

Browse files
authored
Merge pull request rails#54238 from joshuay03/fix-54176
Skip persisted through targets when autosaving collection associations
2 parents 116a5e4 + 0d38f2a commit 20a0e51

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

activerecord/lib/active_record/autosave_association.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,15 @@ def init_internals
297297
# unless the parent is/was a new record itself.
298298
def associated_records_to_validate_or_save(association, new_record, autosave)
299299
if new_record || custom_validation_context?
300-
association && association.target
300+
target = association && association.target
301+
if target && association.reflection.through_reflection
302+
# We expect new through records to be autosaved by their direct parent.
303+
# This prevents already persisted through records from being validated or saved
304+
# more than once.
305+
target.find_all(&:changed_for_autosave?)
306+
else
307+
target
308+
end
301309
elsif autosave
302310
association.target.find_all(&:changed_for_autosave?)
303311
else

activerecord/test/cases/autosave_association_test.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
require "models/cake_designer"
4141
require "models/drink_designer"
4242
require "models/cpk"
43+
require "models/family"
44+
require "models/family_tree"
45+
require "models/user"
4346

4447
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
4548
def test_autosave_works_even_when_other_callbacks_update_the_parent_model
@@ -1147,6 +1150,34 @@ def test_autosave_new_record_with_after_create_callback_and_habtm_association
11471150

11481151
assert_equal 1, post.categories.reload.length
11491152
end
1153+
1154+
FamilyLoadingMiddleAndThroughRecordsBeforeSave = Class.new(Family) do
1155+
before_save do
1156+
family_trees.map(&:member) + members
1157+
end
1158+
end
1159+
1160+
def test_autosave_new_record_with_hmt_and_middle_record_built_by_parent
1161+
family = FamilyLoadingMiddleAndThroughRecordsBeforeSave.new
1162+
family_tree = family.family_trees.build
1163+
family_tree.build_member
1164+
family.save!
1165+
family.reload
1166+
1167+
assert_equal 1, family.family_trees.size
1168+
assert_equal 1, family.members.size
1169+
end
1170+
1171+
def test_autosave_new_record_with_hmt_and_middle_record_built_by_through_record
1172+
family = FamilyLoadingMiddleAndThroughRecordsBeforeSave.new
1173+
member = family.members.build
1174+
family.family_trees.build(member: member)
1175+
family.save!
1176+
family.reload
1177+
1178+
assert_equal 1, family.family_trees.size
1179+
assert_equal 1, family.members.size
1180+
end
11501181
end
11511182

11521183
class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase

0 commit comments

Comments
 (0)