mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #40042 from leequarella/or-unscope-inverse
Fix: Ensure association target is only set if there is not a foreign key mismatch
This commit is contained in:
commit
e1b3cf8dc5
2 changed files with 37 additions and 2 deletions
|
@ -131,8 +131,12 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def inversed_from(record)
|
||||
self.target = record
|
||||
@inversed = !!record
|
||||
if inversable?(record)
|
||||
self.target = record
|
||||
@inversed = true
|
||||
else
|
||||
@inversed = false
|
||||
end
|
||||
end
|
||||
alias :inversed_from_queries :inversed_from
|
||||
|
||||
|
@ -325,6 +329,19 @@ module ActiveRecord
|
|||
def enqueue_destroy_association(options)
|
||||
owner.class.destroy_association_async_job&.perform_later(**options)
|
||||
end
|
||||
|
||||
def inversable?(record)
|
||||
record &&
|
||||
((!record.persisted? || !owner.persisted?) || matches_foreign_key?(record))
|
||||
end
|
||||
|
||||
def matches_foreign_key?(record)
|
||||
if foreign_key_for?(record)
|
||||
record.read_attribute(reflection.foreign_key) == owner.id
|
||||
else
|
||||
owner.read_attribute(reflection.foreign_key) == record.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -658,6 +658,24 @@ class InverseBelongsToTests < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_unscope_does_not_set_inverse_when_incorrect
|
||||
interest = interests(:trainspotting)
|
||||
human = interest.human
|
||||
created_human = Human.create(name: "wrong human")
|
||||
found_interest = created_human.interests.or(human.interests).detect { |this_interest| interest.id == this_interest.id }
|
||||
|
||||
assert_equal human, found_interest.human
|
||||
end
|
||||
|
||||
def test_or_does_not_set_inverse_when_incorrect
|
||||
interest = interests(:trainspotting)
|
||||
human = interest.human
|
||||
created_human = Human.create(name: "wrong human")
|
||||
found_interest = created_human.interests.unscope(:where).detect { |this_interest| interest.id == this_interest.id }
|
||||
|
||||
assert_equal human, found_interest.human
|
||||
end
|
||||
|
||||
def test_child_instance_should_be_shared_with_replaced_via_accessor_parent
|
||||
face = Face.first
|
||||
human = Human.new(name: "Charles")
|
||||
|
|
Loading…
Reference in a new issue