52

I need to convert a hash like the one provided below into readable YAML. It looks like I can feed YAML::load a string, but I think I need to convert it first into something like this:

hostname1.test.com:
  public: 51
  private: 10

{"hostname1.test.com"=>
   {"public"=>"51", "private"=>"10"},
 "hostname2.test.com"=>
   {"public"=>"192", "private"=>"12"}
}

I'm not sure exactly how to do that conversion into that string effectively though.

I looked through the HASH documentation and couldn't find anything for to_yaml. I found it by searching for to_yaml which becomes available when you require yaml. I also tried to use the Enumerable method collect but got confused when I needed to iterate through the value (another hash).

I'm trying to use "Converting hash to string in Ruby" as a reference. My thought was then to feed that into YAML::load and that would generate the YAML I wanted.

Community
  • 1
  • 1
Shail Patel
  • 1,764
  • 5
  • 30
  • 46
  • Did you read through Ruby's [YAML documentation](http://www.ruby-doc.org/stdlib-2.0/libdoc/yaml/rdoc/YAML.html)? How about "[Yaml Cookbook at the YamlForRuby site](http://www.yaml.org/YAML_for_ruby.html)? Also, your supplied hash isn't valid. Should it be an array of hashes, or a hash of hashes? – the Tin Man Jul 10 '13 at 17:04
  • You also should have supplied code showing what you've tried, along with an explanation of what didn't work. -1 for not showing any effort. – the Tin Man Jul 10 '13 at 17:11
  • Added the work that I did prior to finding the to_yaml method. – Shail Patel Jul 10 '13 at 17:23
  • 1
    `to_yaml` is not part of Hash or Object or any class by default. You *HAVE* to `require 'yaml'` someplace in the script, or in something you require, for YAML to extend Object, Hash, and other methods. See the edit to my answer. – the Tin Man Jul 10 '13 at 20:40

3 Answers3

74

Here's how I'd do it:

require 'yaml'

HASH_OF_HASHES = {
  "hostname1.test.com"=> {"public"=>"51", "private"=>"10"},
  "hostname2.test.com"=> {"public"=>"192", "private"=>"12"}
}

ARRAY_OF_HASHES = [
  {"hostname1.test.com"=> {"public"=>"51", "private"=>"10"}},
  {"hostname2.test.com"=> {"public"=>"192", "private"=>"12"}}
]

puts HASH_OF_HASHES.to_yaml
puts
puts ARRAY_OF_HASHES.to_yaml

Which outputs:

---
hostname1.test.com:
  public: '51'
  private: '10'
hostname2.test.com:
  public: '192'
  private: '12'

---
- hostname1.test.com:
    public: '51'
    private: '10'
- hostname2.test.com:
    public: '192'
    private: '12'

The Object class has a to_yaml method. I used that and it generated the YAML file correctly.

No, it doesn't.

This is from a freshly opened IRB session:

Object.instance_methods.grep(/to_yaml/)
=> []
require 'yaml'
=> true
Object.instance_methods.grep(/to_yaml/)
=> [:psych_to_yaml, :to_yaml, :to_yaml_properties]
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
6

You can use the to_yaml method on a hash for this I believe after you require yaml

Shail Patel
  • 1,764
  • 5
  • 30
  • 46
  • 2
    Hash doesn't have a `to_yaml` method. – the Tin Man Jul 10 '13 at 17:13
  • 6
    [Object does *not* have a `to_yaml` method](http://ruby-doc.org/core-2.0/Object.html). Only the [YAML](http://ruby-doc.org/stdlib-2.0/libdoc/yaml/rdoc/YAML.html) class has it, and it extends other classes when it's required. – the Tin Man Jul 10 '13 at 20:38
2

You can use YAML.dump:

YAML.dump(a: 2, b: 1)
=> "---\n:a: 2\n:b: 1\n

One advantage of YAML.dump over to_yaml is that it's easier to infer what the code is doing because most people read from left to right.

builder-7000
  • 7,131
  • 3
  • 19
  • 43