Skip to content
Browse files

Merge pull request #12834 from dredozubov/has_one_association_replace…

…ment

Fixes problem with replacing has_one association record with itself
Conflicts:
	activerecord/CHANGELOG.md
  • Loading branch information...
1 parent b671aea commit 59a99ed846df0e605573d9de8fdac0fdb5ad0ca7 @senny senny committed Nov 11, 2013
6 activerecord/CHANGELOG.md
@@ -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*
+
* Fix uninitialized constant TransactionState error when Marshall.load is used on an Active Record result.
Fixes #12790
View
6 activerecord/lib/active_record/associations/has_one_association.rb
@@ -26,11 +26,13 @@ def replace(record, save = true)
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
18 activerecord/test/cases/associations/has_one_associations_test.rb
@@ -525,16 +525,30 @@ def test_has_one_transaction
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

0 comments on commit 59a99ed

Please sign in to comment.
Something went wrong with that request. Please try again.