[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Question on IO objects, initialize, and yaml

Joel VanderWerf

12/11/2006 8:12:00 PM

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.

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

1 Answer

Joel VanderWerf

12/11/2006 8:30:00 PM

0

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