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