46
votes

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.

3
Did you read through Ruby's YAML documentation? How about "Yaml Cookbook at the YamlForRuby site? Also, your supplied hash isn't valid. Should it be an array of hashes, or a hash of hashes? - the Tin Man
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
Added the work that I did prior to finding the to_yaml method. - Shail Patel
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

3 Answers

69
votes

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]
6
votes

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

0
votes

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.