Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何控制使用YAML序列化哪些字段_Ruby_Yaml - Fatal编程技术网

Ruby 如何控制使用YAML序列化哪些字段

Ruby 如何控制使用YAML序列化哪些字段,ruby,yaml,Ruby,Yaml,比如说, class Point attr_accessor :x, :y, :pointer_to_something_huge end 我只想序列化x和y,其他的都保留为nil。我建议在类中添加一个自定义的到\u yaml方法,该方法构造您想要的特定yaml格式 我知道to_json接受参数来告诉它要序列化哪些属性,但我找不到to_yaml的参数 以下是to_yaml的实际来源: # File activerecord/lib/active_record/base.rb, line 6

比如说,

class Point
  attr_accessor :x, :y, :pointer_to_something_huge
end

我只想序列化x和y,其他的都保留为nil。

我建议在类中添加一个自定义的
到\u 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中包含特定的键/值对

经过大量的搜索,我无意中发现:

class Point
  def to_yaml_properties
    ["@x", "@y"]
  end
end
此方法用于选择YAML序列化的属性。有一种更强大的方法涉及到自定义发射器(在Psych中),但我不知道它是什么

此解决方案仅适用于Ruby 1.8;在Ruby 1.9中,
to_yaml
已经切换到使用Psych,Matt使用
encode_with
的答案是合适的解决方案;如果您使用的是Ruby 1.9,那么一种更适合未来的方法是使用
encode\u with

class Point
  def encode_with coder
    coder['x'] = @x
    coder['y'] = @y
  end
end
def init_with coder
  @x = coder['x']
  @y = coder['y']
end
在这种情况下,这就是您所需要的,因为默认设置是在从Yaml加载时将新对象的相应实例变量设置为适当的值,但在更复杂的情况下,您可以使用
init\u with

class Point
  def encode_with coder
    coder['x'] = @x
    coder['y'] = @y
  end
end
def init_with coder
  @x = coder['x']
  @y = coder['y']
end

如果需要所有字段,但不需要几个字段,可以这样做

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上测试如果你有大量的实例变量,你可以使用这样一个简短的版本

def encode_with( coder )
  %w[ x y a b c d e f g ].each { |v| coder[ v ] = instance_variable_get "@#{v}" }
end
您应该使用#encode_with,因为#to#yaml_属性已被弃用:

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太危险,并且您只需要过滤掉一个实例变量,那么您可能更喜欢这样。所有其他变量都需要一个访问器:

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

仅供参考:如果您使用覆盖
ActiveRecord::Base
子类的
#init_,请记住返回
self
,否则任何时候您实例化模型时都会返回nil。
子类进行编码还有什么效果
到_json
以及朋友?在回答中添加一些注释。