diff options
Diffstat (limited to 'activerecord/lib/active_record/coders/yaml_column.rb')
-rw-r--r-- | activerecord/lib/active_record/coders/yaml_column.rb | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb new file mode 100644 index 0000000000..11559141c7 --- /dev/null +++ b/activerecord/lib/active_record/coders/yaml_column.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "yaml" + +module ActiveRecord + module Coders # :nodoc: + class YAMLColumn # :nodoc: + attr_accessor :object_class + + def initialize(attr_name, object_class = Object) + @attr_name = attr_name + @object_class = object_class + check_arity_of_constructor + end + + def dump(obj) + return if obj.nil? + + assert_valid_value(obj, action: "dump") + YAML.dump obj + end + + def load(yaml) + return object_class.new if object_class != Object && yaml.nil? + return yaml unless yaml.is_a?(String) && /^---/.match?(yaml) + obj = YAML.load(yaml) + + assert_valid_value(obj, action: "load") + obj ||= object_class.new if object_class != Object + + obj + end + + def assert_valid_value(obj, action:) + unless obj.nil? || obj.is_a?(object_class) + raise SerializationTypeMismatch, + "can't #{action} `#{@attr_name}`: was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}" + end + end + + private + + def check_arity_of_constructor + load(nil) + rescue ArgumentError + raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor." + end + end + end +end |