From ad5824bde0f63d5bb2e33b7fe86904d1fbd7ff95 Mon Sep 17 00:00:00 2001
From: Yuki Nishijima <mail@yukinishijima.net>
Date: Tue, 6 Jan 2015 04:31:08 -0800
Subject: AR::RecordNotSaved & RecordNotDestroyed should include an error
 message

When `AR::Base.save!` or `AR::Base.destroy!` is called and an exception
is raised, the exception doesn't have any error message or has a weird
message like `#<FailedBulb:0x0000000907b4b8>`. Give a better message so
we can easily understand why it's failing to save/destroy.
---
 activerecord/lib/active_record/errors.rb                           | 4 ++--
 activerecord/lib/active_record/persistence.rb                      | 4 ++--
 activerecord/test/cases/associations/has_many_associations_test.rb | 3 ++-
 activerecord/test/cases/callbacks_test.rb                          | 2 ++
 4 files changed, 8 insertions(+), 5 deletions(-)

(limited to 'activerecord')

diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
index 98aee77557..0f1759abaa 100644
--- a/activerecord/lib/active_record/errors.rb
+++ b/activerecord/lib/active_record/errors.rb
@@ -71,9 +71,9 @@ module ActiveRecord
   class RecordNotDestroyed < ActiveRecordError
     attr_reader :record
 
-    def initialize(record)
+    def initialize(message, record = nil)
       @record = record
-      super()
+      super(message)
     end
   end
 
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index da8f4d027a..466175690e 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -148,7 +148,7 @@ module ActiveRecord
     # Attributes marked as readonly are silently ignored if the record is
     # being updated.
     def save!(*args)
-      create_or_update(*args) || raise(RecordNotSaved.new(nil, self))
+      create_or_update(*args) || raise(RecordNotSaved.new("Failed to save the record", self))
     end
 
     # Deletes the record in the database and freezes this instance to
@@ -193,7 +193,7 @@ module ActiveRecord
     # and #destroy! raises ActiveRecord::RecordNotDestroyed.
     # See ActiveRecord::Callbacks for further details.
     def destroy!
-      destroy || raise(ActiveRecord::RecordNotDestroyed, self)
+      destroy || raise(RecordNotDestroyed.new("Failed to destroy the record", self))
     end
 
     # Returns an instance of the specified +klass+ with the attributes of the
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 14cdf37f46..2c4e2a875c 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -2131,11 +2131,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
     car = Car.create!
     original_child = FailedBulb.create!(car: car)
 
-    assert_raise(ActiveRecord::RecordNotDestroyed) do
+    error = assert_raise(ActiveRecord::RecordNotDestroyed) do
       car.failed_bulbs = [FailedBulb.create!]
     end
 
     assert_equal [original_child], car.reload.failed_bulbs
+    assert_equal "Failed to destroy the record", error.message
   end
 
   test 'updates counter cache when default scope is given' do
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index 3ae4a6eade..73ac30e547 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -451,6 +451,7 @@ class CallbacksTest < ActiveRecord::TestCase
       assert !david.save
       exc = assert_raise(ActiveRecord::RecordNotSaved) { david.save! }
       assert_equal exc.record, david
+      assert_equal "Failed to save the record", exc.message
     end
 
     david = ImmutableDeveloper.find(1)
@@ -494,6 +495,7 @@ class CallbacksTest < ActiveRecord::TestCase
       assert !david.destroy
       exc = assert_raise(ActiveRecord::RecordNotDestroyed) { david.destroy! }
       assert_equal exc.record, david
+      assert_equal "Failed to destroy the record", exc.message
     end
     assert_not_nil ImmutableDeveloper.find_by_id(1)
 
-- 
cgit v1.2.3