Potty Training YAML

- 2010-05-10 21:46:17

Ran into a problem today where I have a class with a few attributes on it, but I only want a certain three of those attributes to appear in the YAML dump of a class instance.

Diving straight into a code example--lets say we have a Contact class, and we only want to dump the name, email and website attributes.

require "yaml"

class Contact
    attr_accessor :name, :email, :website, :telephone

    # helper method to make setting up easy
    def initialize params={}
      params.each do |key, value|
        meffod = "#{key.to_s}="
        send(meffod, value) if respond_to?(meffod)
      end
    end
end

# And create an instance for us to play with
caius = Contact.new(
  :name => "Caius",
  :email => "dev@caius.name",
  :website => "http://caius.name/",
  :telephone => "12345"
)

As we'd expect when dumping this, all instance variables get dumped out:

print caius.to_yaml
# >> --- !ruby/object:Contact 
# >> email: dev@caius.name
# >> name: Caius
# >> telephone: "12345"
# >> website: http://caius.name/

Initially I tried to override to_yaml and unset the instance variables I didn't want showing up, but that just made them show up empty. After digging around a bit more, I happened across the Type Families page in the yaml4r docs, which right at the bottom mentions to_yaml_properties.

Turns out to_yaml_properties returns an array of instance variable names (as strings) that should be dumped out as part of the object. A quick method definition later, and we're only dumping the variables we want. (See my Ruby Shortcuts post if you don't know what %w() does)

class Contact
    def to_yaml_properties
        %w(@name @email @website)
    end
end

And now we dump the class, expecting only the three attributes to be outputted:

print caius.to_yaml
# >> --- !ruby/object:Contact 
# >> name: Caius
# >> email: dev@caius.name
# >> website: http://caius.name/

Success!

2 Comments on Potty Training YAML

  1. with such a simple class, using a hash to serialize is a more flexible approach.

    kenny stone - 2010-05-12 03:13:26
  2. @kenny:

    Not if you want it to serialise as a Contact class though. In the use case I had the local class was being serialised and sent to a remote service, which unserialised it and did something with the data. Both sides have custom methods, and I had an extra attribute locally that if I'd sent across would've confused the remote service. If I'd sent a serialised hash it would've been really confused!


About You

Comment