ActiveRecord serialize using JSON instead of YAML
Solution 1:
In Rails 3.1 you can just
class Form < ActiveRecord::Base
serialize :column, JSON
end
Hope that helps
Solution 2:
In Rails 3.1 you can use custom coders with serialize
.
class ColorCoder
# Called to deserialize data to ruby object.
def load(data)
end
# Called to convert from ruby object to serialized data.
def dump(obj)
end
end
class Fruits < ActiveRecord::Base
serialize :color, ColorCoder.new
end
Hope this helps.
References:
Definition of serialize
:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb#L556
The default YAML coder that ships with rails: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/coders/yaml_column.rb
And this is where the call to the load
happens:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods/read.rb#L132
Solution 3:
Update
See mid's high rated answer below for a much more appropriate Rails >= 3.1 answer. This is a great answer for Rails < 3.1.
Probably this is what you're looking for.
Form.find(:first).to_json
Update
1) Install 'json' gem:
gem install json
2) Create JsonWrapper class
# lib/json_wrapper.rb
require 'json'
class JsonWrapper
def initialize(attribute)
@attribute = attribute.to_s
end
def before_save(record)
record.send("#{@attribute}=", JsonWrapper.encrypt(record.send("#{@attribute}")))
end
def after_save(record)
record.send("#{@attribute}=", JsonWrapper.decrypt(record.send("#{@attribute}")))
end
def self.encrypt(value)
value.to_json
end
def self.decrypt(value)
JSON.parse(value) rescue value
end
end
3) Add model callbacks:
#app/models/user.rb
class User < ActiveRecord::Base
before_save JsonWrapper.new( :name )
after_save JsonWrapper.new( :name )
def after_find
self.name = JsonWrapper.decrypt self.name
end
end
4) Test it!
User.create :name => {"a"=>"b", "c"=>["d", "e"]}
PS:
It's not quite DRY, but I did my best. If anyone can fix after_find
in User
model, it'll be great.