aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2011-01-08 19:39:40 +0000
committerAaron Patterson <aaron.patterson@gmail.com>2011-01-11 13:45:06 -0800
commit1bc71ed9607ba88c21c14b670a4308c8549f3941 (patch)
tree89acbe329f1c54cddc192b42e2115ed6abec3e15 /activerecord
parentc47c54140246f4e5b49376ae9c408c85968ed6c3 (diff)
downloadrails-1bc71ed9607ba88c21c14b670a4308c8549f3941.tar.gz
rails-1bc71ed9607ba88c21c14b670a4308c8549f3941.tar.bz2
rails-1bc71ed9607ba88c21c14b670a4308c8549f3941.zip
When assigning a has_one, if the existing record fails to be removed from the association, raise an error
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/has_one_association.rb16
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb12
2 files changed, 23 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index 9135c60009..a4332a0511 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -20,7 +20,7 @@ module ActiveRecord
load_target
if @target && @target != record
- remove_target(@reflection.options[:dependent])
+ remove_target!(@reflection.options[:dependent])
end
if record
@@ -55,13 +55,19 @@ module ActiveRecord
record
end
- def remove_target(method)
- case method
- when :delete, :destroy
+ def remove_target!(method)
+ if [:delete, :destroy].include?(method)
@target.send(method)
else
@target[@reflection.foreign_key] = nil
- @target.save if @target.persisted? && @owner.persisted?
+
+ if @target.persisted? && @owner.persisted?
+ unless @target.save
+ @target[@reflection.foreign_key] = @target.send("#{@reflection.foreign_key}_was")
+ raise RecordNotSaved, "Failed to remove the existing associated #{@reflection.name}. " +
+ "The record failed to save when after its foreign key was set to nil."
+ end
+ end
end
end
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index f004d46c98..46459df7c5 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -308,4 +308,16 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert new_ship.new_record?
assert orig_ship.destroyed?
end
+
+ def test_replacement_failure_due_to_existing_record_should_raise_error
+ pirate = pirates(:blackbeard)
+ pirate.ship.name = nil
+
+ assert !pirate.ship.valid?
+ assert_raise(ActiveRecord::RecordNotSaved) do
+ pirate.ship = ships(:interceptor)
+ end
+ assert_equal ships(:black_pearl), pirate.ship
+ assert_equal pirate.id, pirate.ship.pirate_id
+ end
end