例如,
class Point
attr_accessor :x, :y, :pointer_to_something_huge
end
我只想序列化x和y,并将其他所有内容保留为nil。
答案 0 :(得分:23)
在Ruby 1.9中,to_yaml_properties
is deprecated;如果你使用的是Ruby 1.9,那么更加面向未来的方法就是使用encode_with
:
class Point
def encode_with coder
coder['x'] = @x
coder['y'] = @y
end
end
在这种情况下,您只需要,因为默认情况下从Yaml加载时将新对象的相应实例变量设置为适当的值,但在更完整的情况下,您可以使用init_with
:
def init_with coder
@x = coder['x']
@y = coder['y']
end
答案 1 :(得分:8)
经过大量的搜索,我偶然发现了这个:
class Point
def to_yaml_properties
["@x", "@y"]
end
end
此方法用于选择YAML序列化的属性。有一种更强大的方法涉及自定义发射器(在Psych中),但我不知道它是什么。
此解决方案仅适用于Ruby 1.8;在Ruby 1.9中,to_yaml
已经转向使用Psych,Matt使用encode_with
的答案是适当的解决方案。
答案 2 :(得分:1)
如果你想要所有领域,只有少数,你可以这样做
def encode_with(coder)
vars = instance_variables.map{|x| x.to_s}
vars = vars - ['@unwanted_field1', '@unwanted_field2']
vars.each do |var|
var_val = eval(var)
coder[var.gsub('@', '')] = var_val
end
end
这会阻止您手动管理列表。在Ruby 1.9上测试
答案 3 :(得分:1)
如果你有很多实例变量,你可以使用像这样的短版本
def encode_with( coder )
%w[ x y a b c d e f g ].each { |v| coder[ v ] = instance_variable_get "@#{v}" }
end
答案 4 :(得分:0)
您应该使用#encode_with,因为不推荐使用#to_yaml_properties:
def encode_with(coder)
# remove @unwanted and @other_unwanted variable from the dump
(instance_variables - [:@unwanted, :@other_unwanted]).each do |var|
var = var.to_s # convert symbol to string
coder[var.gsub('@', '')] = eval(var) # set key and value in coder hash
end
end
或者你可能更喜欢这个,如果eval太危险了,你只需要过滤掉一个实例var。所有其他变量需要有一个访问者:
attr_accessor :keep_this, :unwanted
def encode_with(coder)
# reject @unwanted var, all others need to have an accessor
instance_variables.reject{|x|x==:@unwanted}.map(&:to_s).each do |var|
coder[var[1..-1]] = send(var[1..-1])
end
end
答案 5 :(得分:-2)
我建议在您的类中添加一个自定义to_yaml
方法,以构建您想要的特定yaml格式。
我知道to_json
接受参数来告诉它要序列化的属性,但我找不到to_yaml
的相同内容。
以下是to_yaml
的实际来源:
# File activerecord/lib/active_record/base.rb, line 653
def to_yaml(opts = {}) #:nodoc:
if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
super
else
coder = {}
encode_with(coder)
YAML.quick_emit(self, opts) do |out|
out.map(taguri, to_yaml_style) do |map|
coder.each { |k, v| map.add(k, v) }
end
end
end
end
所以看起来可能有机会设置opts
,以便它包含yaml中的特定键/值对。