mirror of https://github.com/rails/rails
Raise a descriptive error when a store column is misconfigured
If a developer has neglected to use a structured column type (hstore or json) or to declare a serializer with `ActiveRecord.store`: ```ruby class User < ActiveRecord::Base store_accessor :settings, :notifications end ``` then a `ConfigurationError` will now be raised with a descriptive error message when the accessor is read or written: ```ruby puts user.notifications # ActiveRecord::ConfigurationError: the column 'settings' has not # been configured as a store. Please make sure the column is # declared serializable via 'ActiveRecord.store' or, if your # database supports it, use a structured column type like hstore or # json. ``` Previously, in this situation, a `NoMethodError` was raised when the accessor was read or written: ```ruby puts user.notifications # NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text ``` Raising a descriptive exception should help developers understand more quickly what's wrong and how to fix it. Closes #51699
This commit is contained in:
parent
43e4916483
commit
2bf7e25243
|
@ -1,3 +1,19 @@
|
|||
* Improve `ActiveRecord::Store` to raise a descriptive exception if the column is not either
|
||||
structured (e.g., PostgreSQL +hstore+/+json+, or MySQL +json+) or declared serializable via
|
||||
`ActiveRecord.store`.
|
||||
|
||||
Previously, a `NoMethodError` would be raised when the accessor was read or written:
|
||||
|
||||
NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text
|
||||
|
||||
Now, a descriptive `ConfigurationError` is raised:
|
||||
|
||||
ActiveRecord::ConfigurationError: the column 'metadata' has not been configured as a store.
|
||||
Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your
|
||||
database supports it, use a structured column type like hstore or json.
|
||||
|
||||
*Mike Dalessio*
|
||||
|
||||
* Fix inference of association model on nested models with the same demodularized name.
|
||||
|
||||
E.g. with the following setup:
|
||||
|
|
|
@ -217,7 +217,11 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def store_accessor_for(store_attribute)
|
||||
type_for_attribute(store_attribute).accessor
|
||||
type_for_attribute(store_attribute).tap do |type|
|
||||
unless type.respond_to?(:accessor)
|
||||
raise ConfigurationError, "the column '#{store_attribute}' has not been configured as a store. Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your database supports it, use a structured column type like hstore or json."
|
||||
end
|
||||
end.accessor
|
||||
end
|
||||
|
||||
class HashAccessor # :nodoc:
|
||||
|
|
|
@ -359,4 +359,18 @@ class StoreTest < ActiveRecord::TestCase
|
|||
test "prefix/suffix do not affect stored attributes" do
|
||||
assert_equal [:secret_question, :two_factor_auth, :login_retry], Admin::User.stored_attributes[:configs]
|
||||
end
|
||||
|
||||
test "store_accessor raises an exception if the column is not either serializable or a structured type" do
|
||||
user = Class.new(Admin::User) do
|
||||
store_accessor :name, :color
|
||||
end.new
|
||||
|
||||
assert_raises ActiveRecord::ConfigurationError do
|
||||
user.color
|
||||
end
|
||||
|
||||
assert_raises ActiveRecord::ConfigurationError do
|
||||
user.color = "blue"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue