Multiple Documents, One File

Earlier, I mentioned that three dashes are used to mark the start of a new YAML section known as a document. For example, let’s assume you want to save two arrays, arr1 and arr2, to a file, multidoc.yml. Here arr1 is an array containing two nested arrays, and arr2 is an array containing two CD objects:

multi_docs.rb

arr1 =  [   ["The Groovesters", "Groovy Tunes", 12 ],
            [  "Dolly Parton", "Greatest Hits", 38 ]
        ]

arr2 =  [ CD.new("Gribbit Mcluskey", "Fab Songs", 22),
          CD.new("Wayne Snodgrass", "Singalong-a-Snodgrass", 24)
        ]

This is my routine to dump these arrays to YAML and write them to a file (as explained in Chapter 13, the 'w' argument causes the file to be opened for writing):

File.open( 'multidoc.yml', 'w' ){ |f|
    YAML.dump( arr1, f )
    YAML.dump( arr2, f )
}

If you now look at the file multidoc.yml, you’ll see that the data has been saved as two separate “documents,” each one beginning with three dashes:

---
- - The Groovesters
  - Groovy Tunes
  - 12
- - Dolly Parton
  - Greatest Hits
  - 38
---
- !ruby/object:CD
  artist: Gribbit Mcluskey
  name: Fab Songs
  numtracks: 22
- !ruby/object:CD
  artist: Wayne Snodgrass
  name: Singalong-a-Snodgrass
  numtracks: 24

Now, I need to find a way of reconstructing these arrays by reading in the data as two documents. This is where the load_documents method comes to the rescue. The load_documents method calls a block and passes to it each consecutive document. Here is an example of how to use this method in order to reconstruct two arrays (placed inside another array, $new_arr) from the two YAML documents:

File.open( 'multidoc.yml' ) {|f|
    YAML.load_documents( f ) { |doc|
      $new_arr << doc
    }
 }

You can verify that $new_arr has been initialized with the two arrays by executing the following:

p( $new_arr )

This displays an array containing the loaded data in two nested arrays:

[[["The Groovesters", "Groovy Tunes", 12], ["Dolly Parton",
 "Greatest Hits", 38]], [#<CD:0x2c30e98 @artist="Gribbit Mcluskey", @name="Fab
 Songs", @numtracks=22>, #<CD:0x2c30ad8 @artist="Wayne Snodgrass",
 @name="Singalong-a-Snodgrass", @numtracks=24>]]

Because this is a bit unmanageable, you might prefer to display each of the nested arrays individually using an index into the outer array:

p( $new_arr[0] )
p( $new_arr[1] )

The previous assumes that you know, in advance, the number of nested arrays available. Alternatively, here’s a more generic way of doing the same thing, using the each method to pass all available items into a block; this works with any number of arrays:

$new_arr.each{ |arr| p( arr ) }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.251.57