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

Fixes problem with replacing has_one association record with itself

This commit is contained in:
Denis Redozubov 2013-11-09 19:38:27 +04:00
parent 9d664b18df
commit 3ed5642e69
3 changed files with 26 additions and 4 deletions

View file

@ -1,3 +1,9 @@
* Fix bug where has_one associaton record update result in crash, when replaced with itself.
Fixes #12834.
*Denis Redozubov*, *Sergio Cambra*
* Log bind variables after they are type casted. This makes it more
transparent what values are actually sent to the database.

View file

@ -26,11 +26,13 @@ module ActiveRecord
load_target
return self.target if !(target || record)
if (target != record) || record.changed?
assigning_another_record = target != record
if assigning_another_record || record.changed?
save &&= owner.persisted?
transaction_if(save) do
remove_target!(options[:dependent]) if target && !target.destroyed?
remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record
if record
set_owner_attributes(record)

View file

@ -509,16 +509,30 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert_no_queries { Firm.new.account = account }
end
def test_has_one_assignment_triggers_save_on_change
def test_has_one_assignment_dont_triggers_save_on_change_of_same_object
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
ship = pirate.build_ship(name: 'old name')
ship.save!
ship.name = 'new name'
assert ship.changed?
assert_queries(1) do
# One query for updating name, not triggering query for updating pirate_id
pirate.ship = ship
end
assert_equal 'new name', pirate.ship.reload.name
end
def test_has_one_assignment_triggers_save_on_change_on_replacing_object
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
ship = pirate.build_ship(name: 'old name')
ship.save!
new_ship = Ship.create(name: 'new name')
assert_queries(2) do
# One query for updating name and second query for updating pirate_id
pirate.ship = ship
pirate.ship = new_ship
end
assert_equal 'new name', pirate.ship.reload.name