Ruby-on-rails ActiveRecord 使用 JSON 而不是 YAML 进行序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2080347/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ActiveRecord serialize using JSON instead of YAML
提问by Toby Hede
I have a model that uses a serialized column:
我有一个使用序列化列的模型:
class Form < ActiveRecord::Base
serialize :options, Hash
end
Is there a way to make this serialization use JSON instead of YAML?
有没有办法让这个序列化使用 JSON 而不是 YAML?
回答by Justas L.
In Rails 3.1 you can just
在 Rails 3.1 中,你可以
class Form < ActiveRecord::Base
serialize :column, JSON
end
Hope that helps
希望有帮助
回答by balu
In Rails 3.1 you can use custom coders with serialize.
在 Rails 3.1 中,您可以将自定义编码器与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
定义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
Rails 附带的默认 YAML 编码器:https: //github.com/rails/rails/blob/master/activerecord/lib/active_record/coders/yaml_column.rb
And this is where the call to the loadhappens:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods/read.rb#L132
这就是调用load发生的地方:https:
//github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods/read.rb#L132
回答by St.Woland
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.
有关更合适的 Rails >= 3.1 答案,请参阅下面的中等评分答案。这是 Rails < 3.1 的一个很好的答案。
Probably this is what you're looking for.
可能这就是你要找的。
Form.find(:first).to_json
Update
更新
1) Install 'json' gem:
1)安装'json' gem:
gem install json
2) Create JsonWrapper class
2) 创建 JsonWrapper 类
# 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:
3) 添加模型回调:
#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!
4) 测试一下!
User.create :name => {"a"=>"b", "c"=>["d", "e"]}
PS:
PS:
It's not quite DRY, but I did my best. If anyone can fix after_findin Usermodel, it'll be great.
不是很干,但我尽力了。如果任何人都可以修复after_find的User模型,这将是巨大的。
回答by Toby Hede
My requirements didn't need a lot of code re-use at this stage, so my distilled code is a variation on the above answer:
我的需求在这个阶段不需要大量代码重用,所以我的提炼代码是上述答案的变体:
require "json/ext"
before_save :json_serialize
after_save :json_deserialize
def json_serialize
self.options = self.options.to_json
end
def json_deserialize
self.options = JSON.parse(options)
end
def after_find
json_deserialize
end
Cheers, quite easy in the end!
干杯,最后很容易!
回答by caribu
The serialize :attr, JSONusing composed_ofmethod works like this:
的serialize :attr, JSON使用composed_of方法是这样的:
composed_of :auth,
:class_name => 'ActiveSupport::JSON',
:mapping => %w(url to_json),
:constructor => Proc.new { |url| ActiveSupport::JSON.decode(url) }
where url is the attribute to be serialized using json and auth is the new method available on your model that saves its value in json format to the url attribute. (not fully tested yet but seems to be working)
其中 url 是要使用 json 序列化的属性,auth 是模型上可用的新方法,它将其值以 json 格式保存到 url 属性。(尚未完全测试,但似乎正在工作)
回答by Benjamin Atkin
I wrote my own YAML coder, that takes a default. Here is the class:
我编写了自己的 YAML 编码器,它采用默认设置。这是课程:
class JSONColumn
def initialize(default={})
@default = default
end
# this might be the database default and we should plan for empty strings or nils
def load(s)
s.present? ? JSON.load(s) : @default.clone
end
# this should only be nil or an object that serializes to JSON (like a hash or array)
def dump(o)
JSON.dump(o || @default)
end
end
Since loadand dumpare instance methods it requires an instance to be passed as the second argument to serializein the model definition. Here's an example of it:
由于load和dump是实例方法,它需要一个实例作为serialize模型定义中的第二个参数传递。这是一个例子:
class Person < ActiveRecord::Base
validate :name, :pets, :presence => true
serialize :pets, JSONColumn.new([])
end
I tried creating a new instance, loading an instance, and dumping an instance in IRB, and it all seemed to work properly. I wrote a blog postabout it, too.
回答by Aleran
A simpler solution is to use composed_ofas described in this blog post by Michael Rykov. I like this solution because it requires the use of fewer callbacks.
一个更简单的解决方案是composed_of按照Michael Rykov 的这篇博客文章中的描述使用。我喜欢这个解决方案,因为它需要使用更少的回调。
Here is the gist of it:
这是它的要点:
composed_of :settings, :class_name => 'Settings', :mapping => %w(settings to_json),
:constructor => Settings.method(:from_json),
:converter => Settings.method(:from_json)
after_validation do |u|
u.settings = u.settings if u.settings.dirty? # Force to serialize
end
回答by Andrew Lank
Aleran, have you used this method with Rails 3? I've somewhat got the same issue and I was heading towards serialized when I ran into this post by Michael Rykov, but commenting on his blog is not possible, or at least on that post. To my understanding he is saying that you do not need to define Settings class, however when I try this it keeps telling me that Setting is not defined. So I was just wondering if you have used it and what more should have been described? Thanks.
Aleran,您在 Rails 3 中使用过这种方法吗?我遇到了同样的问题,当我遇到 Michael Rykov 的这篇文章时,我正朝着连载的方向前进,但不可能在他的博客上发表评论,或者至少在那篇文章上发表评论是不可能的。据我了解,他是说您不需要定义 Settings 类,但是当我尝试此操作时,它一直告诉我未定义 Setting 。所以我只是想知道你是否使用过它,还有什么应该被描述的?谢谢。

