Thank you so much for your help guys. Those debugging lessons will prove
invaluable in the future. Thanks for teaching that to me.
> On Wed, 2011-12-28 at 22:56 -0700, Michael Havens wrote:
> > I hate it when you are trying to learn something and what you are
> > learning from is incomplete or wrong. This is the beginning of a ruby
> > script I am writing which will (in the section shown) erase a file.
> > ruby tells me that line 15 is wrong! It says:
> >
> > ex16.rb:15: undefined local variable or method `file' for
> > main:Object (NameError)
> >
> > I am guessing that what line 15 is doing is telling the program to
> > make file 'target' smaller but it needs to know how small and the guy
> > who writes Learn Code the Hard Way forgot to include that in his
> > tutorial. Or else I'm wrong and in that case please show me where I
> > am wrong.
> >
> > 1 filename = ARGV.first #argument at command line is given a name
> > 2 script = $0 #script is now titled file's name
> > 3
> > 4 puts "We're going to erase the contents of #{filename}."
> > 5 puts "If you don't want to do that hit CTRL-C."
> > 6 puts "If you do want to do that then hit RETURN."
> > 7
> > 8 print "? "
> > 9 STDIN.gets #it waits for input before going on
> > 10
> > 11 puts "Opening the file..."
> > 12 target = File.open(filename, 'w') #tells it to open filename or to
> > write it if non-existant
> > 13
> > ^^^^is this right?^^^^^^^^^^
> > 14 puts "Truncating the file. Goodbye!"
> > 15 target.truncate(target.size)
>
> My Diagnostic process:
>
> First I input your program without any comments:
> ---------------------------------------------------------------------------
> #!/usr/bin/env ruby
>
> filename = ARGV.first
> script = $0
>
> puts "We're going to erase the contents of #{filename}"
> puts "If you don't want to do that hit CTRL-C"
> puts "If you want to do that then hit ENTER"
>
> print "?"
> STDIN.gets
>
> puts "Opening the file..."
> target = File.open(filename, 'w')
>
> puts "Truncating the file. Goodbye!"
> target.truncate(target.size)
> ---------------------------------------------------------------------------
>
> Then I ran it without any parameters:
> ---------------------------------------------------------------------------
> kfries@kfries-laptop:Kevin$ ./sample.rb
> We're going to erase the contents of
> If you don't want to do that hit CTRL-C
> If you want to do that then hit ENTER
> ?
> Opening the file...
> ./sample.rb:14:in `initialize': can't convert nil into String
> (TypeError)
> from ./sample.rb:14:in `open'
> from ./sample.rb:14
> kfries@kfries-laptop:Kevin$
> ---------------------------------------------------------------------------
>
> OK not good form, added a line after the filename = as such:
> raise "Missing parameter\n\n\tUseage: $0 <filename>" if filename.nil?
>
> ran again with no parameter:
> ---------------------------------------------------------------------------
> kfries@kfries-laptop:Kevin$ ./sample.rb
> ./sample.rb:4: Missing parameter (RuntimeError)
>
> Useage: $0 <filename>
> kfries@kfries-laptop:Kevin$
> ---------------------------------------------------------------------------
>
> Much better, always remember, any time you ask for input, then use it
> (as
> opposed to press enter to continue), validate it. In this case, I just
> verified
> that something was entered, not that it was correct.
>
> Next I generated a sample file by doing an ls on /usr/bin, then tried to
> truncate
> that file with your program.
> ---------------------------------------------------------------------------
> kfries@kfries-laptop:Kevin$ ls /usr/bin > junk.txt
> kfries@kfries-laptop:Kevin$ ./sample.rb junk.txt
> We're going to erase the contents of junk.txt
> If you don't want to do that hit CTRL-C
> If you want to do that then hit ENTER
> ?
> Opening the file...
> Truncating the file. Goodbye!
> ./sample.rb:18: undefined method `size' for #<File:junk.txt>
> (NoMethodError)
> kfries@kfries-laptop:Kevin$ ls -l
> total 4
> -rw-rw-r-- 1 kfries kfries 0 2011-12-29 09:30 junk.txt
> -rwxrwxr-x 1 kfries kfries 425 2011-12-29 09:27 sample.rb
> kfries@kfries-laptop:Kevin$
> ---------------------------------------------------------------------------
>
> OK, better, it did what it was supposed to do, but then errored out.
>
> The error states that the method .size does not exist on the object
> File.
>
> Lets see (using Ruby) what it does support:
> ---------------------------------------------------------------------------
> kfries@kfries-laptop:Kevin$ irb
> irb(main):001:0> target = File.open("junk.txt", "w")
> => #<File:junk.txt>
> irb(main):002:0> target.size
> NoMethodError: undefined method `size' for #<File:junk.txt>
> from (irb):2
> from :0
> irb(main):003:0> target.methods
> => ["stat", "fileno", "find", "inspect", "tty?", "tap", "seek", "<<",
> "print", "clone", "binmode", "take", "object_id", "__send__",
> "public_methods", "read_nonblock", "reject", "lines", "ctime",
> "instance_variable_defined?", "pos", "minmax", "readlines", "freeze",
> "equal?", "closed?", "member?", "each", "sort", "extend", "partition",
> "getc", "each_cons", "readbyte", "send", "pos=", "close_read", "any?",
> "each_with_index", "methods", "lstat", "to_io", "detect", "hash",
> "putc", "dup", "take_while", "sysseek", "instance_variables", "to_enum",
> "bytes", "write_nonblock", "collect", "eof", "min_by", "eql?", "reopen",
> "sort_by", "enum_cons", "ungetc", "group_by", "id", "instance_eval",
> "truncate", "flock", "close_write", "one?", "enum_with_index", "to_i",
> "singleton_methods", "each_line", "fsync", "find_index", "puts",
> "taint", "ioctl", "drop", "instance_variable_get", "frozen?",
> "enum_for", "chars", "chmod", "readpartial", "map", "display",
> "instance_of?", "max_by", "method", "syswrite", "grep", "to_a", "flush",
> "first", "instance_exec", "type", "isatty", "none?", "reverse_each",
> "protected_methods", "find_all", "each_byte", "atime", "sync", "==",
> "min", "gets", "===", "eof?", "fcntl", "drop_while",
> "instance_variable_set", "path", "write", "each_slice", "chown",
> "sync=", "getbyte", "inject", "respond_to?", "kind_of?", "minmax_by",
> "close", "to_s", "sysread", "count", "printf", "tell", "class", "zip",
> "private_methods", "=~", "tainted?", "__id__", "each_char", "mtime",
> "lineno", "select", "readline", "rewind", "max", "untaint", "nil?",
> "entries", "pid", "cycle", "enum_slice", "lineno=", "readchar",
> "reduce", "read", "include?", "is_a?", "all?"]
> irb(main):004:0> quit
> kfries@kfries-laptop:Kevin$
> ---------------------------------------------------------------------------
>
> OK, using IRB, I can confirm that the truncate command should work, and
> the error message did not indicate a problem with that. It also does
> not support size, and your error message did indicate that. So, the
> error message is telling you, that size does not make sense on the File
> object, and IRB, and the methods command confirms this.
>
> So, what should be in there?
>
> Well, RubyDoc is your friend, far more than any book can be. I looked
> up File::truncate for ruby 1.8.7 (the version on my Ubuntu system) at
> the following URL:
>
> http://ruby-doc.org/core-1.8.7/File.html#method-c-truncate
>
> And it gave me this:
> ---------------------------------------------------------------------------
> truncate(file_name, integer) => 0
>
> Truncates the file file_name to be at most integer bytes long. Not
> available on all platforms.
>
> f = File.new("out", "w")
> f.write("1234567890") #=> 10
> f.close #=> nil
> File.truncate("out", 5) #=> 0
> File.size("out") #=> 5
> ---------------------------------------------------------------------------
>
> So, it is looking for an integer, to indicate how large you want the
> file. It also shows the file method being used! So what went wrong???
> IRB is showing no size method, and the documents shows it valid?
>
> Well, you fell into a common problem of understanding scope. All
> languages deal with this problem, and it manifests itself in lots of
> different ways.
>
> In this case, size() is a class method, not an instance method. What
> this means is that, I can call size() against the class, and feed it a
> filename, but it is not defined in a derived object. So, instead of
> target.size, use File.size(filename).
>
> Making this change the the program gives me this:
> ---------------------------------------------------------------------------
> #!/usr/bin/env ruby
>
> filename = ARGV.first
> raise "Missing parameter\n\n\tUseage: $0 <filename>" if filename.nil?
> script = $0
>
> puts "We're going to erase the contents of #{filename}"
> puts "If you don't want to do that hit CTRL-C"
> puts "If you want to do that then hit ENTER"
>
> print "?"
> STDIN.gets
>
> puts "Opening the file..."
> target = File.open(filename, 'w')
>
> puts "Truncating the file. Goodbye!"
> target.truncate(File.size(filename))
> ---------------------------------------------------------------------------
>
> Now lets test it:
> ---------------------------------------------------------------------------
> kfries@kfries-laptop:Kevin$ ls /usr/bin > junk.txt
> kfries@kfries-laptop:Kevin$ ls -la
> total 36
> drwxrwxr-x 2 kfries kfries 4096 2011-12-29 10:00 .
> drwxrwxrwt 22 root root 4096 2011-12-29 09:46 ..
> -rw-rw-r-- 1 kfries kfries 22634 2011-12-29 10:02 junk.txt
> -rwxrwxr-x 1 kfries kfries 433 2011-12-29 10:00 sample.rb
> kfries@kfries-laptop:Kevin$ ./sample.rb junk.txt
> We're going to erase the contents of junk.txt
> If you don't want to do that hit CTRL-C
> If you want to do that then hit ENTER
> ?
> Opening the file...
> Truncating the file. Goodbye!
> kfries@kfries-laptop:Kevin$ ls -l
> total 4
> -rw-rw-r-- 1 kfries kfries 0 2011-12-29 10:03 junk.txt
> -rwxrwxr-x 1 kfries kfries 433 2011-12-29 10:00 sample.rb
> kfries@kfries-laptop:Kevin$
> ---------------------------------------------------------------------------
>
> SUCCESS!!
>
> I hope seeing me step through the debugging was helpful to you
>
> Kevin
>
>
> ---------------------------------------------------
> PLUG-discuss mailing list - PLUG-discuss@lists.plug.phoenix.az.us
> To subscribe, unsubscribe, or to change your mail settings:
> http://lists.PLUG.phoenix.az.us/mailman/listinfo/plug-discuss
>