Skip to content

Commit

Permalink
fix: duplicate active record objects on inverse_of
Browse files Browse the repository at this point in the history
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 <terence.li@shopify.com>
Co-authored-by: Dave Rose <dave.rose@shopify.com>
  • Loading branch information
3 people committed Oct 13, 2021
1 parent f2be2b0 commit 6f6c441
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,10 @@ def replace_on_target(record, skip_callbacks, replace:, inversing: false)

yield(record) if block_given?

if !index && @replaced_or_added_targets.include?(record)
index = @target.index(record)
end

@replaced_or_added_targets << record if inversing || index || record.new_record?

if index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,15 @@ def test_with_has_many_inversing_does_not_trigger_association_callbacks_on_set_w
end
end

def test_with_hash_many_inversing_does_not_add_duplicate_associated_objects
with_has_many_inversing(Interest) do
human = Human.new
interest = Interest.new(human: human)
human.interests << interest
assert_equal 1, human.interests.size
end
end

def test_unscope_does_not_set_inverse_when_incorrect
interest = interests(:trainspotting)
human = interest.human
Expand Down

0 comments on commit 6f6c441

Please sign in to comment.