1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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.
This commit is contained in:
Aaron Weiner 2013-02-27 18:17:29 -05:00
parent 48c21e3255
commit 53f18f2c54
3 changed files with 21 additions and 0 deletions

View file

@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ## ## 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 * Postgresql timestamp with time zone (timestamptz) datatype now returns a
ActiveSupport::TimeWithZone instance instead of a string ActiveSupport::TimeWithZone instance instead of a string

View file

@ -15,6 +15,9 @@ module ActiveRecord
# and if the inheritance column is attr accessible, it initializes an # and if the inheritance column is attr accessible, it initializes an
# instance of the given subclass instead of the base class # instance of the given subclass instead of the base class
def new(*args, &block) 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 (attrs = args.first).is_a?(Hash)
if subclass = subclass_from_attrs(attrs) if subclass = subclass_from_attrs(attrs)
return subclass.new(*args, &block) return subclass.new(*args, &block)

View file

@ -307,6 +307,20 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal("last_read", ex.errors[0].attribute) assert_equal("last_read", ex.errors[0].attribute)
end 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 def test_create_after_initialize_without_block
cb = CustomBulb.create(:name => 'Dude') cb = CustomBulb.create(:name => 'Dude')
assert_equal('Dude', cb.name) assert_equal('Dude', cb.name)