Skip to content

Commit 2bf7e25

Browse files
committed
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 rails#51699
1 parent 43e4916 commit 2bf7e25

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

activerecord/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
* Improve `ActiveRecord::Store` to raise a descriptive exception if the column is not either
2+
structured (e.g., PostgreSQL +hstore+/+json+, or MySQL +json+) or declared serializable via
3+
`ActiveRecord.store`.
4+
5+
Previously, a `NoMethodError` would be raised when the accessor was read or written:
6+
7+
NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text
8+
9+
Now, a descriptive `ConfigurationError` is raised:
10+
11+
ActiveRecord::ConfigurationError: the column 'metadata' has not been configured as a store.
12+
Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your
13+
database supports it, use a structured column type like hstore or json.
14+
15+
*Mike Dalessio*
16+
117
* Fix inference of association model on nested models with the same demodularized name.
218

319
E.g. with the following setup:

activerecord/lib/active_record/store.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,11 @@ def write_store_attribute(store_attribute, key, value) # :doc:
217217
end
218218

219219
def store_accessor_for(store_attribute)
220-
type_for_attribute(store_attribute).accessor
220+
type_for_attribute(store_attribute).tap do |type|
221+
unless type.respond_to?(:accessor)
222+
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."
223+
end
224+
end.accessor
221225
end
222226

223227
class HashAccessor # :nodoc:

activerecord/test/cases/store_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,4 +359,18 @@ def test_convert_store_attributes_from_Hash_to_HashWithIndifferentAccess_saving_
359359
test "prefix/suffix do not affect stored attributes" do
360360
assert_equal [:secret_question, :two_factor_auth, :login_retry], Admin::User.stored_attributes[:configs]
361361
end
362+
363+
test "store_accessor raises an exception if the column is not either serializable or a structured type" do
364+
user = Class.new(Admin::User) do
365+
store_accessor :name, :color
366+
end.new
367+
368+
assert_raises ActiveRecord::ConfigurationError do
369+
user.color
370+
end
371+
372+
assert_raises ActiveRecord::ConfigurationError do
373+
user.color = "blue"
374+
end
375+
end
362376
end

0 commit comments

Comments
 (0)