diff options
Diffstat (limited to 'activerecord/lib/active_record/type/serialized.rb')
-rw-r--r-- | activerecord/lib/active_record/type/serialized.rb | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb new file mode 100644 index 0000000000..0a2f6cb9fb --- /dev/null +++ b/activerecord/lib/active_record/type/serialized.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module ActiveRecord + module Type + class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc: + undef to_yaml if method_defined?(:to_yaml) + + include ActiveModel::Type::Helpers::Mutable + + attr_reader :subtype, :coder + + def initialize(subtype, coder) + @subtype = subtype + @coder = coder + super(subtype) + end + + def deserialize(value) + if default_value?(value) + value + else + coder.load(super) + end + end + + def serialize(value) + return if value.nil? + unless default_value?(value) + super coder.dump(value) + end + end + + def inspect + Kernel.instance_method(:inspect).bind(self).call + end + + def changed_in_place?(raw_old_value, value) + return false if value.nil? + raw_new_value = encoded(value) + raw_old_value.nil? != raw_new_value.nil? || + subtype.changed_in_place?(raw_old_value, raw_new_value) + end + + def accessor + ActiveRecord::Store::IndifferentHashAccessor + end + + def assert_valid_value(value) + if coder.respond_to?(:assert_valid_value) + coder.assert_valid_value(value, action: "serialize") + end + end + + def force_equality?(value) + coder.respond_to?(:object_class) && value.is_a?(coder.object_class) + end + + private + + def default_value?(value) + value == coder.load(nil) + end + + def encoded(value) + unless default_value?(value) + coder.dump(value) + end + end + end + end +end |