1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Bugfix foreign key replacement in inverse association

when model is added to collection association
This commit is contained in:
Bogdan Gusiev 2017-12-27 15:52:35 +02:00
parent 17ad4eb6fb
commit a84c76573f
3 changed files with 17 additions and 13 deletions

View file

@ -12,17 +12,20 @@ module ActiveRecord
if record if record
raise_on_type_mismatch!(record) raise_on_type_mismatch!(record)
update_counters_on_replace(record) update_counters_on_replace(record)
replace_keys(record)
set_inverse_instance(record) set_inverse_instance(record)
@updated = true @updated = true
else else
decrement_counters decrement_counters
remove_keys
end end
self.target = record self.target = record
end end
def target=(record)
replace_keys(record)
super
end
def default(&block) def default(&block)
writer(owner.instance_exec(&block)) if reader.nil? writer(owner.instance_exec(&block)) if reader.nil?
end end
@ -78,11 +81,8 @@ module ActiveRecord
end end
def replace_keys(record) def replace_keys(record)
owner[reflection.foreign_key] = record._read_attribute(reflection.association_primary_key(record.class)) owner[reflection.foreign_key] = record ?
end record._read_attribute(reflection.association_primary_key(record.class)) : nil
def remove_keys
owner[reflection.foreign_key] = nil
end end
def foreign_key_present? def foreign_key_present?

View file

@ -13,12 +13,7 @@ module ActiveRecord
def replace_keys(record) def replace_keys(record)
super super
owner[reflection.foreign_type] = record.class.base_class.name owner[reflection.foreign_type] = record ? record.class.base_class.name : nil
end
def remove_keys
super
owner[reflection.foreign_type] = nil
end end
def different_target?(record) def different_target?(record)

View file

@ -2509,6 +2509,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_same car, new_bulb.car assert_same car, new_bulb.car
end end
test "reattach to new objects replaces inverse association and foreign key" do
bulb = Bulb.create!(car: Car.create!)
assert bulb.car_id
car = Car.new
car.bulbs << bulb
assert_equal car, bulb.car
assert_nil bulb.car_id
end
test "in memory replacement maintains order" do test "in memory replacement maintains order" do
first_bulb = Bulb.create! first_bulb = Bulb.create!
second_bulb = Bulb.create! second_bulb = Bulb.create!