aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/type/serialized.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/type/serialized.rb')
-rw-r--r--activerecord/lib/active_record/type/serialized.rb71
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