How to load a Hash from a File?

YAML is a very universal format for storing data in a way that can be transferred between apps and programming languages. JSON is another alternate, which is very common in web sites.

I use YAML for things like configuration files because it's very easily read and modified. For instance, this Ruby structure:

irb(main):002:0> foo = { 'a' => 1, 'b' => [2, 3], 'c' => { 'd' => 4, 'e' => 5 } }
{
    "a" => 1,
    "b" => [
        [0] 2,
        [1] 3
    ],
    "c" => {
        "d" => 4,
        "e" => 5
    }
}

Looks like this when converted to YAML:

irb(main):003:0> puts foo.to_yaml
--- 
a: 1
b: 
- 2
- 3
c: 
  d: 4
  e: 5

You could save that to a file:

File.open('foo.yaml', 'w') { |fo| fo.puts foo.to_yaml }

and read it back in:

bar = YAML.load_file('foo.yaml')
{
    "a" => 1,
    "b" => [
        [0] 2,
        [1] 3
    ],
    "c" => {
        "d" => 4,
        "e" => 5
    }
}

Similarly, using JSON:

puts foo.to_json
{"a":1,"b":[2,3],"c":{"d":4,"e":5}}

You can save the JSON to a file like you would with YAML and then reload it and turn it back into the hash. It's a bit different syntax though:

irb(main):011:0> File.open('foo.json', 'w') { |fo| fo.puts foo.to_json }
nil
irb(main):012:0> bar = JSON.parse(File.read('foo.json'))
{
    "a" => 1,
    "b" => [
        [0] 2,
        [1] 3
    ],
    "c" => {
        "d" => 4,
        "e" => 5
    }
}

The big win with either is any language that can read YAML or JSON can read those files and use the data, either reading OR writing it.

Doing the string substitution is very easy once you have a hash, because Ruby String's gsub understands hashes. This is from the docs:

If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.

This means you can do something like this:

foo = 'Jackdaws love my giant sphinx of quartz'
bar = { 'quartz' => 'rosy quartz', 'sphinx' => 'panda' }
foo.gsub(Regexp.union(bar.keys), bar)
"Jackdaws love my giant panda of rosy quartz"

You do have to watch out for word-boundary collisions doing the substitution, but the \b flag in a pattern can be of help. Making that work is an exercise for the reader.


See Marshal.load and Marshal.dump.

Also, you could look into serializing the hash to a yaml file and then read/save it back via YAML.

Tags:

Ruby

Hashtable