Larry Edelstein wrote:
> Hi all -
> 
> I want to write a config file in YAML.  In this file I will store a
> small graph of objects in an array:
> 
> - !mydomain,mydate/Company
>   name: TuesdayCo
>   subthings:
>     - !mydomain,mydate/Person
>       name: Ruby Tuesday
>     - !mydomain,mydate/Person
>       name: Tuesday Weld
> - !mydomain,myDate
>   name: FridayCo
>   subthings:
>     etc.
> 
> Then I want to read in this file and get an array of Company objects,
> each of which has an array of Person objects.  I'm defining these
> classes myself.  I've tried using add_domain_type and hoped to get
> instances of my classes, but instead I got instances of
> YAML::DomainType.
> 
> How should I do this?

Here's the only way I know to do this (I'm not sure if add_domain_type 
is another way):

require 'yaml'

# This assumes that all your objects will serialize as hashes ("maps")
module Base
   def to_yaml( opts = {} )
     YAML::quick_emit( object_id, opts ) do |out|
       out.map( taguri, to_yaml_style ) do |map|
         to_yaml_properties.each do |m|
           map.add( m, send( m ) )
         end
       end
     end
   end

   module BaseModuleMethods
     def yaml_new( klass, tag, val )
       unless Hash === val
         raise YAML::TypeError, "Invalid #{self}: " + val.inspect
         ## do more error checking here, if desired
       end

       name, type = YAML.read_type_class( tag, self )
       st = type.new
       val.each do |k,v|
         st.send( "#{k}=", v )
       end
       st
     end
   end

   def self.included mod
     mod.extend BaseModuleMethods
   end
end

class Company
   include Base

   attr_accessor :name, :subthings
   def initialize name = nil
     @name = name
   end

   yaml_as "tag:my.domain,2007:Company"

   def to_yaml_properties
     ["name", "subthings"]
   end
end

class Person
   include Base

   attr_accessor :name
   def initialize name = nil
     @name = name
   end

   yaml_as "tag:my.domain,2007:Person"

   def to_yaml_properties
     ["name"]
   end
end

co = Company.new "TuesdayCo"
co.subthings = [
   Person.new("Ruby Tuesday"),
   Person.new("Tuesday Weld")
]

co_yaml = co.to_yaml
puts co_yaml
# ==>
# --- !my.domain,2007/Company
# name: TuesdayCo
# subthings:
# - !my.domain,2007/Person
#   name: Ruby Tuesday
# - !my.domain,2007/Person
#   name: Tuesday Weld

co2 = YAML.load(co_yaml)
p co2

# ==>
#<Company:0xb7ce3cfc @subthings=[#<Person:0xb7ce44cc @name="Ruby 
Tuesday">, #<Person:0xb7ce3ef0 @name="Tuesday Weld">], @name="TuesdayCo">


# Check that error-checking works by
# giving the parser an array instead of a hash:
s = <<END
--- !my.domain,2007/Company
- 1
- 2
END

begin
   p YAML.load(s)
rescue YAML::TypeError => ex
   puts ex.message   # Invalid Company: [1, 2]
end

-- 
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407