Skip to content

Commit 6f6c441

Browse files
jstncarvalhoTerence Lidrose-shopify
committed
fix: duplicate active record objects on inverse_of
Fixes a bug that causes duplicate references to the same object to be added to the collection association on an active_record object when inverse_of is used. In cases where has_many_inversing is set to true, the set_inverse_instance function calls target= on collection_association during concat resulting in multiple appends to target. This only occurs for new records. This PR introduces changes that sets the index so the duplicate object replaces the original. Closes issue rails#43222. Co-authored-by: Terence Li <[email protected]> Co-authored-by: Dave Rose <[email protected]>
1 parent f2be2b0 commit 6f6c441

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

activerecord/lib/active_record/associations/collection_association.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,10 @@ def replace_on_target(record, skip_callbacks, replace:, inversing: false)
456456

457457
yield(record) if block_given?
458458

459+
if !index && @replaced_or_added_targets.include?(record)
460+
index = @target.index(record)
461+
end
462+
459463
@replaced_or_added_targets << record if inversing || index || record.new_record?
460464

461465
if index

activerecord/test/cases/associations/inverse_associations_test.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,15 @@ def test_with_has_many_inversing_does_not_trigger_association_callbacks_on_set_w
766766
end
767767
end
768768

769+
def test_with_hash_many_inversing_does_not_add_duplicate_associated_objects
770+
with_has_many_inversing(Interest) do
771+
human = Human.new
772+
interest = Interest.new(human: human)
773+
human.interests << interest
774+
assert_equal 1, human.interests.size
775+
end
776+
end
777+
769778
def test_unscope_does_not_set_inverse_when_incorrect
770779
interest = interests(:trainspotting)
771780
human = interest.human

0 commit comments

Comments
 (0)