Joel VanderWerf
12/11/2006 8:30:00 PM
Joel VanderWerf wrote:
> Mark Noworolski wrote:
>> Say I have a class with pseudo code as follows:
>> class Test
>> def initialize
>> @a=1
>> @b=File.open("file+Time.now or similar")
>> end
>> end
>>
>> Now, imagine that I use this class for a while and then I want to dump
>> it to
>> a YAML file.
>>
>> When I restart my code, I want it to read in stuff from the YAML file
>> (if it
>> exists) and use that as a starting point to work from (basically, I am
>> saving state in the yaml file). You'll note that I cannot just do this as
>> is, because reading in from YAML does not initialize the class, so @b
>> would
>> not be initialized correctly on restart.
>>
>> I'd like to just initialize the thing, then read in the YAML file to
>> overwrite the state with the saved values. Is there some extremely
>> obvious
>> ruby way to do this or something equivalent?
>
> A possible alternative is to be lazy about constructing the non-dumpable
> stuff:
>
> [~] cat test.rb
> require 'yaml'
>
> class Test
> def initialize
> @a = 1
> end
> def b
> @b ||= File.open(__FILE__) # just for testing
> end
> end
>
> t = Test.new
> t2 = YAML.load(YAML.dump(t))
>
> line = t2.b.gets
> p line
>
> [~] ruby test.rb
> "require 'yaml'\n
>
>
> If you do this, other parts of your code shouldn't access @b directly.
> Instead, call the #b method.
>
That's not quite right. If you use #b and then dump/load and try to use
#b on the new object, you get an error:
t = Test.new
t2 = YAML.load(YAML.dump(t))
line = t2.b.gets
p line
t3 = YAML.load(YAML.dump(t2))
line = t3.b.gets
p line
Output:
"require 'yaml'\n"
test.rb:23:in `gets': uninitialized stream (IOError)
from test.rb:23
You can "fix" this by adding a #to_yaml method to your class that clears @b:
class Test
def to_yaml(*)
@b = nil
super
end
end
Then t3.b.gets doesn't fail. But whether this "fix" is right for your
class is another question...
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407