diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 12fe38d6ca08d..dbf52431bd14c 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -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: diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb index fbaf233275d91..995d5c8fde326 100644 --- a/activerecord/lib/active_record/store.rb +++ b/activerecord/lib/active_record/store.rb @@ -217,7 +217,11 @@ def write_store_attribute(store_attribute, key, value) # :doc: 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: diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index b4cdc91ab185b..44a161d68192a 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -359,4 +359,18 @@ def test_convert_store_attributes_from_Hash_to_HashWithIndifferentAccess_saving_ 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