aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Weiner <aweiner@mdsol.com>2013-02-27 18:17:29 -0500
committerAaron Weiner <aweiner@mdsol.com>2013-03-03 12:36:51 -0500
commit53f18f2c5475809f7f6c5576aba89d6340a57c06 (patch)
treed1ae1d758acc64933ac592866b5b94745ded553b /activerecord
parent48c21e3255fa2f4b1875ca8616a5ad7706a7a4cb (diff)
downloadrails-53f18f2c5475809f7f6c5576aba89d6340a57c06.tar.gz
rails-53f18f2c5475809f7f6c5576aba89d6340a57c06.tar.bz2
rails-53f18f2c5475809f7f6c5576aba89d6340a57c06.zip
More helpful error message when instantiating an abstract class
Calling a literal ActiveRecord::Base.new raises NoMethodError, since it ends up calling Class.abstract_class? which does not exist. Similarly, instantiating an actual abstract class hits the database, when conventionally it should immediately throw NotImplementedError. ActiveRecord::Base can't be made abstract without breaking many, many things, so check for it separately.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md4
-rw-r--r--activerecord/lib/active_record/inheritance.rb3
-rw-r--r--activerecord/test/cases/base_test.rb14
3 files changed, 21 insertions, 0 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 2eaf388095..2f96a7b5cf 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ##
+* Throw `NotImplementedError` when trying to instantiate Base or an abstract class.
+
+ *Aaron Weiner*
+
* Postgresql timestamp with time zone (timestamptz) datatype now returns a
ActiveSupport::TimeWithZone instance instead of a string
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index e630897a4b..13a8352f13 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -15,6 +15,9 @@ module ActiveRecord
# and if the inheritance column is attr accessible, it initializes an
# instance of the given subclass instead of the base class
def new(*args, &block)
+ if abstract_class? || self == Base
+ raise NotImplementedError, "#{self} is an abstract class and can not be instantiated."
+ end
if (attrs = args.first).is_a?(Hash)
if subclass = subclass_from_attrs(attrs)
return subclass.new(*args, &block)
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index af1845c937..8e6e462404 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -307,6 +307,20 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal("last_read", ex.errors[0].attribute)
end
+ def test_initialize_abstract_class
+ e = assert_raises(NotImplementedError) do
+ FirstAbstractClass.new
+ end
+ assert_equal("FirstAbstractClass is an abstract class and can not be instantiated.", e.message)
+ end
+
+ def test_initialize_base
+ e = assert_raises(NotImplementedError) do
+ ActiveRecord::Base.new
+ end
+ assert_equal("ActiveRecord::Base is an abstract class and can not be instantiated.", e.message)
+ end
+
def test_create_after_initialize_without_block
cb = CustomBulb.create(:name => 'Dude')
assert_equal('Dude', cb.name)