# Question on IO objects, initialize, and yaml

**URL:** <https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936>\
**Category:** Ruby\
**Created:** [December 10, 2006, 9:19pm UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936 "2006-12-10T21:19:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![scorintha](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@scorintha](https://www.ruby-forum.com/u/scorintha)\
**Post date:** [December 10, 2006, 9:19pm UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936/1 "2006-12-10T21:19:55Z")

</div>

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?

Thanks,  
mark

---

<div class="post-metadata">

**Author:** ![scorintha](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@scorintha](https://www.ruby-forum.com/u/scorintha)\
**Post date:** [December 11, 2006, 2:24am UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936/2 "2006-12-11T02:24:32Z")

</div>

On Dec 10, 2006, at 12:19 , Mark N. wrote:

> 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.

Ruby and YAML provide hooks to cause things to happen when you load  
from Marshal or YAML. I think #initialize\_copy gets called for  
Marshal, I don’t know the YAML ones, but they should be easy to find.

> 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?

Don’t do this, use the built-in hooks, that’s what they’re for.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)

I LIT YOUR GEM ON FIRE!

---

<div class="post-metadata">

**Author:** ![scorintha](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@scorintha](https://www.ruby-forum.com/u/scorintha)\
**Post date:** [December 11, 2006, 6:44am UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936/3 "2006-12-11T06:44:56Z")

</div>

I _want_ to use a built-in hook (the ruby way, if you will), if I can  
figure  
out which one and how to use it.

Based on your suggestion, I’ve googled and found this code:  
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/104402](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/104402)

Now, I’ve experimented with initialize\_copy on this code and your  
recommendation, and I cannot get it to do what I want.

Anybody got any other suggestions, or a concrete example for me?  
mark

---

<div class="post-metadata">

**Author:** ![scorintha](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@scorintha](https://www.ruby-forum.com/u/scorintha)\
**Post date:** [December 11, 2006, 9:13pm UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936/4 "2006-12-11T21:13:40Z")

</div>

Mark N. wrote:

> a YAML file.  
> 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.

---

<div class="post-metadata">

**Author:** ![scorintha](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@scorintha](https://www.ruby-forum.com/u/scorintha)\
**Post date:** [December 11, 2006, 9:29pm UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936/5 "2006-12-11T21:29:43Z")

</div>

Joel VanderWerf wrote:

> > it to  
> > I’d like to just initialize the thing, then read in the YAML file to  
> > class Test
> 
> 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…

---

<div class="post-metadata">

**Author:** ![scorintha](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/278dde/32.png) [@scorintha](https://www.ruby-forum.com/u/scorintha)\
**Post date:** [December 12, 2006, 1:08am UTC](https://www.ruby-forum.com/t/question-on-io-objects-initialize-and-yaml/78936/6 "2006-12-12T01:08:46Z")

</div>

On Mon, Dec 11, 2006 at 02:43:22PM +0900, Mark N. wrote:

> On 12/10/06, Eric H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Ruby and YAML provide hooks to cause things to happen when you load  
> > from Marshal or YAML. I think #initialize\_copy gets called for  
> > Marshal, I don’t know the YAML ones, but they should be easy to find.
> 
> I _want_ to use a built-in hook (the ruby way, if you will), if I can figure  
> out which one and how to use it.  
> […]  
> Now, I’ve experimented with initialize\_copy on this code and your  
> recommendation, and I cannot get it to do what I want.
> 
> Anybody got any other suggestions, or a concrete example for me?  
> mark

require ‘yaml’  
class Foo  
def initialize  
@foo = 1  
@bar = 2  
end

def yaml\_initialize(tag, val)  
end  
end

foo = Foo.new  
foo # =\> #\<Foo:0xa7dfe614 @bar=2, @foo=1\>  
YAML.load(YAML.dump(foo)) # =\> #Foo:0xa7dfa6e0

class Foo  
def yaml\_initialize(tag, val) # !\> method redefined; discarding old  
yaml\_initialize  
@foo, @bar = val.values\_at(“foo”, “bar”)  
end  
end

YAML.load(YAML.dump(foo)) # =\> #\<Foo:0xa7ddcfc8 @bar=2, @foo=1\>
