Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
94 lines (82 sloc) 2.67 KB
# frozen_string_literal: true
require "active_model"
module StoreModel
module Types
# Implements ActiveModel::Type::Value type for handling an instance of StoreModel::Model
class JsonType < ActiveModel::Type::Value
# Initializes type for model class
#
# @param model_klass [StoreModel::Model] model class to handle
#
# @return [StoreModel::Types::JsonType]
def initialize(model_klass)
@model_klass = model_klass
end
# Returns type
#
# @return [Symbol]
def type
:json
end
# Casts +value+ from DB or user to StoreModel::Model instance
#
# @param value [Object] a value to cast
#
# @return StoreModel::Model
def cast_value(value)
case value
when String then decode_and_initialize(value)
when Hash then @model_klass.new(value)
when @model_klass, nil then value
else raise_cast_error(value)
end
rescue ActiveModel::UnknownAttributeError => e
handle_unknown_attribute(value, e)
end
# Casts a value from the ruby type to a type that the database knows how
# to understand.
#
# @param value [Object] value to serialize
#
# @return [String] serialized value
def serialize(value)
case value
when Hash, @model_klass
ActiveSupport::JSON.encode(value)
else
super
end
end
# Determines whether the mutable value has been modified since it was read
#
# @param raw_old_value [Object] old value
# @param new_value [Object] new value
#
# @return [Boolean]
def changed_in_place?(raw_old_value, new_value)
cast_value(raw_old_value) != new_value
end
private
# rubocop:disable Style/RescueModifier
def decode_and_initialize(value)
decoded = ActiveSupport::JSON.decode(value) rescue nil
@model_klass.new(decoded) unless decoded.nil?
rescue ActiveModel::UnknownAttributeError => e
handle_unknown_attribute(decoded, e)
end
# rubocop:enable Style/RescueModifier
def raise_cast_error(value)
raise StoreModel::Types::CastError,
"failed casting #{value.inspect}, only String, " \
"Hash or #{@model_klass.name} instances are allowed"
end
def handle_unknown_attribute(value, exception)
attribute = exception.attribute.to_sym
value_symbolized = value.symbolize_keys
cast_value(value_symbolized.except(attribute)).tap do |configuration|
configuration.unknown_attributes[attribute.to_s] = value_symbolized[attribute]
end
end
end
end
end
You can’t perform that action at this time.