From c72325277a254f114fe77d6421ba06ddab4ef60d Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 28 Jan 2021 11:18:14 +0900 Subject: [PATCH] Provide a way `decorate_attribute` for attribute type decoration Just an implementation for https://github.com/rails/rails/pull/41139#discussion_r565752925. --- activerecord/lib/active_record/attributes.rb | 6 ++++++ .../test/cases/serialized_attribute_test.rb | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb index fa075d1cdf9fd..30347bc6b7a70 100644 --- a/activerecord/lib/active_record/attributes.rb +++ b/activerecord/lib/active_record/attributes.rb @@ -266,6 +266,12 @@ def load_schema! # :nodoc: end end + def decorate_attribute(name, type_name, default: NO_DEFAULT_PROVIDED, **options) + attribute(name, default: default) do |subtype| + Type.lookup(type_name, **options, subtype: subtype, adapter: Type.adapter_name_from(self)) + end + end + private NO_DEFAULT_PROVIDED = Object.new # :nodoc: private_constant :NO_DEFAULT_PROVIDED diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index a750e572ecea9..35a17ddada352 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -424,6 +424,24 @@ def changed_in_place?(old, new) end end + def test_decorate_attribute_on_serialized_attribute + old_registry = ActiveRecord::Type.registry + ActiveRecord::Type.registry = ActiveRecord::Type.registry.dup + ActiveRecord::Type.register :encrypted, EncryptedType + + klass = Class.new(ActiveRecord::Base) do + self.table_name = Topic.table_name + store :content + decorate_attribute :content, :encrypted + end + + topic = klass.create!(content: { trial: true }) + + assert_equal({ "trial" => true }, topic.content) + ensure + ActiveRecord::Type.registry = old_registry + end + def test_decorated_type_with_type_for_attribute old_registry = ActiveRecord::Type.registry ActiveRecord::Type.registry = ActiveRecord::Type.registry.dup