2

The following code

require 'yaml'

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

  def to_yaml()
    @value + @value
  end
end

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

Generated the following output on Ruby 2.1.3p242:

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

Where I expected it to be

---
- aa
- bb

As if I called to_yaml on every object inside the Array:

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

What am I doing wrong?

omribahumi
  • 2,011
  • 1
  • 17
  • 19

2 Answers2

1

I'm leaving the previous answer as well, since it might come in handy for someone, but here's the better solution.

I've actually over-simplified the original problem. I'm trying to get my custom object to be rendered as a YAML sequence [1, 2, 3, ...]. The previous answer could work for objects that are being rendered as Strings.

Here's the working version:

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

Some references:

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

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

omribahumi
  • 2,011
  • 1
  • 17
  • 19
0

I'm replacing the visit_Array method of the 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

Then, I'm dumping the YAML this way:

a = [MyObject.new("a"), MyObject.new("b")]
visitor = MyVisitor.create
visitor << a
puts visitor.tree.yaml
omribahumi
  • 2,011
  • 1
  • 17
  • 19