Skip to content

Instantly share code, notes, and snippets.

@wojtha
Last active January 15, 2017 10:47
Show Gist options
  • Select an option

  • Save wojtha/182aa8de65d494ef371ad4f86609789f to your computer and use it in GitHub Desktop.

Select an option

Save wojtha/182aa8de65d494ef371ad4f86609789f to your computer and use it in GitHub Desktop.
ActiveRecord serialize loader for ActiveModel::Serializers
class JSONArray
attr_accessor :object_class, :serializer_class
def initialize(object_class, serializer_class = nil)
@object_class = object_class
@serializer_class = serializer_class || object_class.new.active_model_serializer
end
def dump(arr)
return if arr.nil?
unless arr.is_a?(::Array)
raise ::ActiveRecord::SerializationTypeMismatch, "Attribute was supposed to be an Array, but was a #{arr.class}. -- #{arr.inspect}"
end
arr.each do |obj|
unless obj.is_a?(object_class)
raise ::ActiveRecord::SerializationTypeMismatch, "Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
end
end
::ActiveModel::ArraySerializer.new(arr, each_serializer: serializer_class).to_json
end
def load(json)
return [] if json.nil?
arr = ::JSON.parse(json)
unless arr.is_a?(::Array)
raise ::ActiveRecord::SerializationTypeMismatch, "Attribute was supposed to be an Array, but was a #{arr.class}. -- #{arr.inspect}"
end
arr.collect { |obj|
if obj.is_a?(object_class)
obj
else
object_class.new(obj)
end
}
end
end
class JSONModel
attr_accessor :object_class, :serializer_class, :return_nil
def initialize(object_class, serializer_class: nil, return_nil: true)
@object_class = object_class
@serializer_class = serializer_class || object_class.new.active_model_serializer
@return_nil = return_nil
end
def dump(obj)
return if obj.nil?
unless obj.is_a?(object_class)
raise ::ActiveRecord::SerializationTypeMismatch, "Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
end
serializer_class.new(obj).to_json
end
def load(json)
return nil if return_nil && json.nil?
return object_class.new if object_class != Object && json.nil?
return json unless json.is_a?(String)
data = ::JSON.load(json)
data.is_a?(object_class) ? data : object_class.new(data)
end
end
# Example of usage. Topic::Options and Topic::Step are Virtus objects with coercion
# and with included ActiveModel::SerializerSupport
class Topic < ActiveRecord::Base
serialize :options, JSONModel.new(Topic::Options)
serialize :steps, JSONArray.new(Topic::Step)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment