1
0
Fork 0
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:
John Hawthorn 2020-10-28 15:18:28 -07:00 committed by GitHub
commit e1b3cf8dc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 2 deletions

View file

@ -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

View file

@ -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")