Hal Fulton wrote: > For those curious, what I want to do is establish defaults for > fields in an object, such that: > > 1. When I dump an object, fields that still have the default > values will be left unspecified. > 2. When I load an object, unspecified fields will be given their > default values. > Hi, Hal. Good for you, bringing this up again. We didn't finish this discussion at all and the clock has struck loudly here: time to continue. In Hobix, I am currently using a mixin for classes which need the above. This mixin relies upon the presence of a property_map method within those classes, which defines the full set of instance variables which I want to output in YAML, along with whether those fields are optional or not. The mixin also requires default_#{ivar} methods for every instance variable you plan on having a default for. The mixin will use nil as the default, if no such method is found. You could include defaults in the property_map, but I sometimes base the default value of a field on the value of other fields (in the case of file paths), so I use a method for each instead. So, for example, Hobix blog entries only require @title, @content and @author. Other fields are optional and aren't output to YAML if they are blank. The Hobix::Entry#property_map basically looks like this: class Hobix::Entry include ToYamlExtras def property_map [ ['@title', :req], ['@author', :req], ['@contributors', :opt], ['@created', :opt], ['@tagline', :opt], ['@summary', :opt], ['@content', :req] ] end end I'm using an Array to ensure ordering of the elements upon output. Here would be the ToYamlExtras mixin: module ToYamlExtras def to_yaml_properties property_map.find_all do |prop, req| case req when :opt val = nil if respond_to?( "default_#{ prop[1..-1] }" ) val = method( "default_#{ prop[1..-1] }" ).call end val != instance_variable_get( prop ) when :req true end end. collect { |prop, req| prop } end def initialize apply_defaults yield self if block_given? end def apply_defaults property_map.each do |prop, req| name = prop[1..-1] if instance_variable_get( prop ).nil? and respond_to?( "default_#{ name }" ) instance_variable_set( prop, method( "default_#{ name }" ).call ) end end self end end As you can see, the mixin simply defines a to_yaml_properties method, which is a method understood by the YAML library. The to_yaml_properties method should return an Array of instance variable names, in the order they are output. As you can see, the mixin also defines 'initialize', since you'll probably want to apply the defaults even if the object is created programmatically. You'll also need to hook yourself a YAML type for each class. In the case of the Hobix::Entry class, I'm hooking !hobix.com,2004/entry. class Hobix::Entry def to_yaml_type "!hobix.com,2004/entry" end end YAML::add_domain_type( 'hobix.com,2004', 'entry' ) do |type, val| YAML::object_maker( Hobix::Entry, val ).apply_defaults end A script including this mixin and a few tests of the above can be found at: http://whytheluckystiff.net/ruby/yaml-defaults-mixin.rb _why