diff options
-rw-r--r-- | activerecord/lib/active_record/associations/has_one_association.rb | 16 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_one_associations_test.rb | 12 |
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 |