Brian Buckley wrote:
> Hello all,
> 
> I have an immutable class Foo (once a foo object is created its state
> is fixed).  Foo objects have a bunch of attributes so their yaml
> strings are fairly long.
> 
> There is a small set of standard, frequently used foo objects and I
> have defined these as  constants right in the class (newed and set
> each attribute for Foo::FOO1, Foo::FOO2, ... etc.).
> 
> When I YAML one of these standard foos to the database and back, it
> seems inefficient to create and send a big long yaml string describing
> each attribute and then on retrieval to create a whole new Foo object
> when all I really want is to look up an already-made constant.
> 
> Is there a good solution to making the yaml-ing of constants efficient?
> 
> Thanks!
> 
> --Brian Buckley
> 
> foo = Foo:FOO1
> data = foo.to_yaml  # the yaml string here is unnecessarily long
> foo = YAML::load(data)  # and now after retrieval we have an
> additional foo object when we really only need the one original
> constant

The only problem with the following (I think) is that you have to pass
the constant name in when you instantiate. Note that the object ID of
the object returned by YAML.load is the same as the original, so it's
actually the same object.

require 'yaml'

class Foo
  attr_reader :name
  def initialize name
    @name = name
  end

  def is_complex_yaml?
    false
  end
  def to_yaml( opts = {} )
    YAML::quick_emit( nil, opts ) { |out|
      out << "!ruby/foo "
      self.name.to_yaml( :Emitter => out )
    }
  end
end
YAML.add_ruby_type(/^foo/) do |type, val|
  subtype, subclass = YAML.read_type_class(type, Foo)
  val.split(/::/).inject(Object) { |p, n| p.const_get(n)}
end

foo = FOO1 = Foo.new("FOO1")

p foo
data = foo.to_yaml
puts(data)
foo = YAML.load(data)
p foo

__END__

#<Foo:0xb7bff274 @name="FOO1">
--- !ruby/foo FOO1
#<Foo:0xb7bff274 @name="FOO1">


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