Objects in YAML

YAML.rb has means for exporting custom objects to YAML. We've just gone over most of the types that YAML comes with, so we'll start off with some Ruby-specific types supported by YAML.rb. Then we'll cover how YAML.rb represents your custom classes.

Symbols

Ruby Symbols are stored as strings with a '!ruby/symbol' (or '!ruby/sym') type applied:

simple symbol: !ruby/symbol Simple
shortcut syntax: !ruby/sym Simple
symbols in maps:
  !ruby/sym MapKey: !ruby/sym MapValue
Ex. 15: Symbols in YAML

Naturally, Symbols have their own to_yaml method:

puts :Simple.to_yaml
# prints:
#   --- !ruby/sym Simple
Ex. 16: Using to_yaml with Symbols
Ranges

Ranges are store as strings with a '!ruby/range' type. The string is syntactically identical to the Range syntax in your Ruby code:

normal range: !ruby/range 10..20
exclusive range: !ruby/range 11...20
negative range: !ruby/range -1..-5
? !ruby/range 0..40
: range as a map key
Ex. 17: Ranges in YAML

You may use any YAML basic type in your Range, including Integers, Floats, Dates, and Timestamps.

floats: !ruby/range 10.2..21.5
dates: !ruby/range 2001-03-02..2001-09-11
timestamps: !ruby/range 2001-09-03T05:16:23Z..2001-09-04T07:08:13Z
Ex. 18: Other basic types in Ranges

Who knows how useful having other types in your Ranges really is, but it does illustrate the usefulness of YAML.rb's check_implicit, which allows built-in data types to be reparsed in custom types.

Regexps

Not all languages have built-in regular expression support. But for Ruby, regular expressions are a core object, an essential object!

YAML.rb uses YAML's typing mechanism to support the Regexp class. Regexps are represented as a string using the '!ruby/regexp' type:

starts with a b: !ruby/regexp '/^b/'
ends with a z: !ruby/regexp '/z$/'
search for a C or c: !ruby/regexp '/c/i'
Ex. 19: Regexps in YAML

Regexps also have a to_yaml method, which will type and quote the Regexp for you:

puts( /^b/.to_yaml )
# prints:
#   --- !ruby/regexp "/^b/"
Ex. 20: Using to_yaml with Regexps
Objects

As mentioned previously, every Ruby object has a to_yaml method which is introduced when YAML.rb is loaded. This method will generated a generic YAML representation of any Ruby object. The 'ruby/object' type will be used, along with the class name and a dump of the public members of the object.

As a simple example, let's suppose you have a Video class, which you are going to use to organize your Important-Enough-to-Write-a-Ruby-Script-for video collection. Here's your prototype class:

class Video
  attr_accessor :title, :year, :rating
  def initialize( t, y, r )
    @title = t
    @year = y
    @rating = r
  end
end
Ex. 21: Video class

You own two videos, so you create an Array of Videos to represent your video collection.

collection = [ 
  Video.new( "Ishtar", 1987, 8.8 ),
  Video.new( "Dr. Strangelove", 1964, 10.0 )
]
Ex. 22: Your Video collection

When you export the collection to YAML, you'll see each of the videos appear as a '!ruby/object:Video' type:

puts collection.to_yaml
# prints:
#   - !ruby/object:Video
#     title: Ishtar
#     year: 1987
#     rating: 8.8
#   - !ruby/object:Video
#     title: Dr. Strangelove
#     year: 1964
#     rating: 10.0
Ex. 23: Your Videos in YAML

You can actually code your own to_yaml method, as YAML.rb has a rather simple API for doing so. It's the same API used to build Yod, the software which generates this documentation.