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 ) }