This is a bug I ran into today. I’m not sure who’s responsible for
fixing it, but I don’t personally feel up to
the task. I could make it a multi-day project I suppose, but I feel I
have better things to do today, and tomorrow,
I’m posting this here in hopes that someone who reads this list will
know what to do to fix it.
The bug exists in 1.9.2, 1.9.3, and 2.0.0.
I had written a class for vocabulary cards, which I Marshal.dump’ed at
the end of each session. Then I thought that
before I casually dumped the list a second or subsequent time, I should
make sure that, should anything bad happen,
I didn’t completely clobber the dump file. So, using fileutils, I made a
backup copy before dumping, and then removed
it if things went well, or used it to restore the original file if
things didn’t go well.
I found the dump worked the first time, but each in each subsequent
session the dump would fail, evidently because
somewhere in my object graph an IO had crept in as an instance variable.
I was pretty sure I hadn’t done that, so I had
to write some code to traverse the code and look for an IO somewhere. I
found it, and present for your perusal a small test
file that illustrates the problem.
My problem was that I read about fileutils in the pickaxe book (for 1.9
and 2.0), and the example included FileUtils::Verbose,
and I figured that would be fine for starters, as I could then see what
it was doing.
If you copy this to a file and run it, the first time it will not find
the file (“aFoo”), won’t perform the backup, and will successfully
dump the object to the file. The second time, however, it will find the
find, use FileUtil’s cp to make a backup copy, and then
try unsuccessfully to dump the file, which fails because the object
contains an instance of IO. In the example, I catch this
exception and then go on to list the instance variables, and Whoa!, what
the devil are those instance variables “@filutiils_label”
and “@fileutils_output” doing there?
So evidently calling the verbose version of FileUtils#cp creates,
unbeknownst to the user, a few instance variables for its own
use. I suggest there must be a better place to keep this information.
The problem goes away entirely if you just include FileUtils and
not FileUtils::Verbose.
Thanks for listening, here’s the file. Have a nice day,
Bryan
#!/usr/bin/env ruby
require ‘fileutils’
include FileUtils::Verbose
class Foo
def initialize(str)
@foo = str
end
def make_backup_copy
cp(@foo, “#{@foo}.back”) if File.exist?(@foo)
end
def dump_to_file
make_backup_copy
puts “dumping to file #{@foo}”
begin
File.open(@foo, “w”) { |file| Marshal.dump(self, file) }
rescue Exception => exc
puts exc
return
end
puts “dumped to file #{@foo}”
end
end
f = Foo.new(“aFoo”)
f.dump_to_file
puts “instance variables are now #{f.instance_variables}”
and here’s the output from running it twice:
18:18 cards:>./tester.rb
dumping to file aFoo
dumped to file aFoo
instance variables are now [:@foo]
18:18 cards:>./tester.rb
cp aFoo aFoo.back
dumping to file aFoo
can’t dump IO
instance variables are now [:@foo, :@fileutils_output,
:@fileutils_label]