ruby woes

Michael Havens bmike1 at gmail.com
Thu Dec 29 18:39:54 MST 2011


Thank you so much for your help guys. Those debugging lessons will prove
invaluable in the future. Thanks for teaching that to me.

On Thu, Dec 29, 2011 at 10:14 AM, Kevin Fries <kevin at fries-biro.com> wrote:

> 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 at 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 at 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 at kfries-laptop:Kevin$ ./sample.rb
> ./sample.rb:4: Missing parameter (RuntimeError)
>
>        Useage: $0 <filename>
> kfries at 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 at kfries-laptop:Kevin$ ls /usr/bin > junk.txt
> kfries at 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 at 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 at 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 at 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 at 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 at kfries-laptop:Kevin$ ls /usr/bin > junk.txt
> kfries at 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 at 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 at 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 at kfries-laptop:Kevin$
> ---------------------------------------------------------------------------
>
> SUCCESS!!
>
> I hope seeing me step through the debugging was helpful to you
>
> Kevin
>
>
> ---------------------------------------------------
> PLUG-discuss mailing list - PLUG-discuss at lists.plug.phoenix.az.us
> To subscribe, unsubscribe, or to change your mail settings:
> http://lists.PLUG.phoenix.az.us/mailman/listinfo/plug-discuss
>



-- 
:-)~MIKE~(-:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.PLUG.phoenix.az.us/pipermail/plug-discuss/attachments/20111229/c1b211fb/attachment.html>


More information about the PLUG-discuss mailing list