Created
March 19, 2016 11:20
-
-
Save dungdm93/23c1884db3871bab8330 to your computer and use it in GitHub Desktop.
Serializable Attribute
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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