I fixed this - but why does it work?

I am doing an exercise in a tutorial, which is to get this code to run:

1 filename = ARGV.first
2 script = $0
3
4 puts “We’re going to erase #{filename}.”
5 puts “If you don’t want that, hit CTRL-C (^C).”
6 puts “If you do want that, hit RETURN.”
7
8 print "? "
9 STDIN.gets
10
11 puts “Opening the file…”
12 target = File.open(filename, ‘w’)
13
14 puts “Truncating the file. Goodbye!”
15 target.truncate(target.size)
16
17 puts “Now I’m going to ask you for three lines.”
18
19 print “line 1: “; line1 = STDIN.gets.chomp()
20 print “line 2: “; line2 = STDIN.gets.chomp()
21 print “line 3: “; line3 = STDIN.gets.chomp()
22
23 puts “I’m going to write these to the file.”
24
25 target.write(line1)
26 target.write(”\n”)
27 target.write(line2)
28 target.write(”\n”)
29 target.write(line3)
30 target.write(”\n”)
31
32 puts “And finally, we close it.”
33 target.close()

when I tried to run the above I got a No Method Error for size on line
15.

After some experimentation I got the following to run apparently as
expected:

filename = ARGV.first

script = $0

puts “We’re going to erase #{filename}.”

puts “If you don’t want that, hit CTRL-C (^C).”

puts “If you do want that, hit RETURN.”

print "? "

STDIN.gets

puts “Opening the file…”

target = File.open(filename, ‘w’)

puts “Truncating the file. Goodbye!”

flength=File.size(target)
target.truncate(flength)

puts “Now I’m going to ask you for three lines.”

print "line 1: "; line1 = STDIN.gets.chomp()

print "line 2: "; line2 = STDIN.gets.chomp()

print "line 3: "; line3 = STDIN.gets.chomp()

puts “I’m going to write these to the file.”

target.write(line1)

target.write("\n")

target.write(line2)

target.write("\n")

target.write(line3)

target.write("\n")

puts “And finally, we close it.”

target.close()

So why does the file with my change work? Or, if you prefer, why did the
original give a NoMethodError?

probably, because File.size(target) calls the class method which is
defined for File class, while target.size calls an instance method
which is not defined for File class.

On Mon, Oct 17, 2011 at 12:35 AM, Sub Z. [email protected] wrote:

probably, because File.size(target) calls the class method which is
defined for File class, while target.size calls an instance method
which is not defined for File class.

That’s what I assumed too … (based on the printed documentation in
“Programming Ruby 1.9” Pick Axe which only lists the ). But it turns out
both the instance methods and the class method (both on file name
and File object) work.

Also, trying a case where the file could not be created (forced with an
access permission denied) gives another Exception.

So, I cannot reproduce the original problem here … (on Linux)

peterv@ASUS:~$ ls -lrt | tail -3
---------- 1 peterv peterv 0 2011-10-17 00:39 do_not_edit
-rw-r–r-- 1 peterv peterv 12 2011-10-17 00:41 test123
-rw-r–r-- 1 peterv peterv 9 2011-10-17 00:42 test
peterv@ASUS:~$ ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]
peterv@ASUS:~$ irb
001:0> f = File.open(“test”, ‘w’)
=> #<File:test>
002:0> # open for write resets the size to 0
003:0* ^C
003:0> f.size
=> 0
004:0> f2 = File.open(“test123”, ‘r’)
=> #<File:test123>
005:0> f2.size
=> 12
006:0> File.size(f2)
=> 12
007:0> File.size(“test123”)
=> 12
008:0> File.open(‘do_not_edit’, ‘w’)
Errno::EACCES: Permission denied - do_not_edit
from (irb):8:in initialize' from (irb):8:in open’
from (irb):8
from /home/peterv/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `’

HTH,

Peter

I appreciate the help so far. I tried it in Windows under Cygwin and in
Ubuntu with similar results. I just ruby -v’d and got 1.8.7, so
installed 1.9.1 and then tried the the original version using the
command ruby1.9.1. I am sure this surprises no one but me, but it worked
like a charm.

On Mon, Oct 17, 2011 at 1:52 AM, Edwin G. [email protected]
wrote:

I appreciate the help so far. I tried it in Windows under Cygwin and in
Ubuntu with similar results. I just ruby -v’d and got 1.8.7,

OK, that explains. In ruby 1.8.7 it works as documented in the
Pick Axe book (only class method on File, no instance method).

Thanks for clearing that out :slight_smile:

peterv@ASUS:~$ rvm use 1.8.7-p334 Using /home/peterv/.rvm/gems/ruby-1.8.7-p334

peterv@ASUS:~$ ruby -v
ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-linux]

peterv@ASUS:~$ irb
001:0> f1 = File.open(‘test’,‘w’)
=> #<File:test>
002:0> f1.size
NoMethodError: undefined method `size’ for #<File:test>
from (irb):2
003:0> File.size(“test”) # as documented in Pick Axe
=> 0
004:0> File.size(f1)
=> 0

Peter