Ruby Array#to_yaml不会递归调用to_yaml

时间:2015-05-11 09:22:13

标签: ruby yaml

以下代码

require 'yaml'

class MyObject
  def initialize(value)
    @value = value
  end

  def to_yaml()
    @value + @value
  end
end

puts [MyObject.new("a"), MyObject.new("b")]

在Ruby 2.1.3p242上生成以下输出:

---
- !ruby/object:MyObject
  value: a
- !ruby/object:MyObject
  value: b

我预期的地方

---
- aa
- bb

好像我在数组中的每个对象上调用了to_yaml

puts [MyObject.new("a").to_yaml, MyObject.new("b").to_yaml]

我做错了什么?

2 个答案:

答案 0 :(得分:1)

我也离开了上一个答案,因为它可能会派上用场,但这里有更好的解决方案。

我实际上过度简化了原始问题。我试图让我的自定义对象呈现为YAML序列[1, 2, 3, ...]。 上一个答案可能适用于呈现为字符串的对象。

这是工作版本:

require 'yaml'

class MyObject
  def initialize(value)
    @value = value
  end

  def encode_with coder
    coder.tag = nil
    coder.seq = [@value, @value]
  end
end

puts [MyObject.new("a"), MyObject.new("b")].to_yaml

一些参考文献:

http://blog.mustmodify.com/pages/psych-ruby-1-9-yaml

http://ruby-doc.org/stdlib-1.9.3/libdoc/psych/rdoc/Psych/Coder.html

答案 1 :(得分:0)

我正在替换visit_Array

Psych::Visitors::YAMLTree方法
class MyVisitor < Psych::Visitors::YAMLTree
  def visit_Array o
    super o.map { |i| i.respond_to?(:to_yaml) ? i.to_yaml : i }
  end
end

然后,我以这种方式倾销YAML:

a = [MyObject.new("a"), MyObject.new("b")]
visitor = MyVisitor.create
visitor << a
puts visitor.tree.yaml