Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Serializable Attribute
module Serializable
extend ActiveSupport::Concern
module ClassMethods
def dump(obj)
return if obj.nil?
assert_valid_value obj
ActiveSupport::JSON.encode obj
end
def load(json)
return if json.nil?
attrs = ActiveSupport::JSON.decode(json) rescue json
return attrs if attrs.is_a?(self)
self.new.tap do |obj|
obj.attributes = attrs
end
end
private
def assert_valid_value(obj)
unless obj.nil? || obj.is_a?(self)
raise ActiveRecord::SerializationTypeMismatch,
"Attribute was supposed to be a #{self}, but was a #{obj.class}. -- #{obj.inspect}"
end
end
end
def attributes=(params)
unless params.nil? || params.is_a?(Hash)
raise TypeError, "expected a Hash argument, but was #{params.class}"
end
params.each do |attr, value|
# instance_variable_set("@#{attr}", value) create extra attribute if it's not exists,
# whereas +public_send+ only use pre-define attributes
self.public_send("#{attr}=", value)
end if params
end
def attributes
instance_values
end
end
# Migration
class CreateFoos < ActiveRecord::Migration
def change
create_table :foos do |t|
t.json :one
end
end
end
# Model
class Foo < ActiveRecord::Base
serialize :attr, Address
end
# Serializable Attribute
class Address
include Serializable
attr_accessor :street, :city, :country
end
a = Address.new.tap do |obj|
obj.attributes = {"street":"282 Kevin Brook","city":"Imogeneborough","country":"French Guiana"}
end
f = Foo.new attr: a
f.save
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.