How to debug Ruby Programs

Hi,

I’m a newbee to Ruby, can any one you please suggest me ways to debug a
Ruby P…

Regards,
Kittu.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Krishna Mohan wrote:
| Hi,
|
| I’m a newbee to Ruby, can any one you please suggest me ways to debug a
| Ruby P…
|
| Regards,
| Kittu.

puts statements sprinkled in the code, coupled with #inspect, or
ruby=debug.


Phillip G.
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.blogspot.com

Don’t stop with your first draft.
~ - The Elements of Programming Style (Kernighan & Plaugher)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkgW5tQACgkQbtAgaoJTgL8kRACgiHqNZCDPbNQAh8Wb00mH0WQU
b+4An25N0wvain53CqtltelryBGTc5jq
=wkxk
-----END PGP SIGNATURE-----

Hey i didn’t get you…can you give me a small example to use #inspect,
or
ruby=debug.

thanks for the reply.

Krishna Mohan schreef:

Hey i didn’t get you…can you give me a small example to use #inspect,
or
ruby=debug.

thanks for the reply.

command shell

cmd

ruby -debug name.rb
b name.rb:line?

forexample

ruby -debug test.rb
b test.rb:26

then type c

and then s again and again

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Krishna Mohan wrote:
| Hey i didn’t get you…can you give me a small example to use #inspect,
| or
| ruby=debug.

#inspect:
http://ruby-doc.org/core/classes/Object.html#M000358

ruby-debug:
http://www.google.com/search?q=ruby-debug

Particularly:
http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/


Phillip G.
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.blogspot.com

Don’t stop at one bug.
~ - The Elements of Programming Style (Kernighan & Plaugher)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkgW958ACgkQbtAgaoJTgL9L0wCfWvTJ57397j0pPP3OuVw3mcTq
Y/IAnRincIr1xiJ0ueLd3JlVRmN1RUEf
=u5ky
-----END PGP SIGNATURE-----

On Tue, Apr 29, 2008 at 11:05 AM, Krishna Mohan
[email protected] wrote:

Hi,

I’m a newbee to Ruby, can any one you please suggest me ways to debug a
Ruby P…

My major debugging techniques, in order of how useful they tend to be:

  1. Read code carefully, including refactoring it to be more readable.
    Applicable refactorings include renaming methods, renaming variables,
    extracting methods, inlining methods, and restructuring algorithms.
    Adding comments so it is more clear probably don’t count as
    refactoring; I find that useful, too.

  2. As has already been mentioned, use of puts and inspect, for example

Made up example

something.each do |thing_you_are_going_to_process|
puts “Processing #{thing_you_are_going_to_process.inspect}”
… processing here …
end

to see that you’re operating in a sane way. Various forms of this is,
at least for me, the number two major debugging technique

  1. Add tests around parts of your program that are likely to contain
    errors. For instance, I’ve been operating with some slightly complex
    code to drive translation from one database to another lately; instead
    of dealing with bugs in that code, I’ve added tests for each code
    path.

  2. Add invariant checking to your code - ie, check that things that
    should not be able to fail do not, in fact, fail. Here’s an example:

Example paraphrased from some Perl code I did this with yesterday

new_args[‘Created’] =
WebApp::Util.string_to_stamp(old[‘create_date’’])
raise “Unable to translate #{old[‘create_data’].inspect} for
‘Created’” unless new_args[‘Created’]

For more complex programs, it is sometimes very useful to check that
complete data structures are the way they are supposed to be. For
example, in a tree structure where every node is supposed to point at
their parent, you can check with something like this (called as
tree_root.invariant):

class Tree
def internal_invariant
raise “Left #{@left.inspect} has wrong parent in #{self.inspect}”
if @left && @left.parent != self
raise “Right #{@right.inspect} has wrong parent in
#{self.inspect}” if @right && @right.parent != self
@left.internal_invariant if @left
@right.internal_invariant if @right
end
def invariant
raise “Root has parent?” if @parent
internal_invariant
end
end

I find the invariant adding and puts variants to flow over into each
other a bit in practice; I’ll often add extra invariants when doing
debugging, and a bunch of output (puts statatements), and then I use
“cvs diff” to find and eliminate the puts statements while committing
the new invariant checks.

Bonus tip: Eliminating stuff from a diff is often most easily done by
storing the diff in a file, editing out everything you want to keep,
and then doing patch -R < file_with_diffs_to_remove

Eivind.

Eivind.

Eivind E. wrote:

I find the invariant adding and puts variants to flow over into each
other a bit in practice; I’ll often add extra invariants when doing
debugging, and a bunch of output (puts statatements), and then I use
“cvs diff” to find and eliminate the puts statements while committing
the new invariant checks.

You can put debug code (invariant checks, and puts), flush with the left
margin (unindented). Then these lines can be grepped for with ^\w, more
or less. They also stand out when you scan the code visually.

This is enough of a reason to choose ruby over python, IMO.

ThoML wrote:

It’s a pity ruby -rdebug doesn’t seem functional with ruby 1.9.

which version ?

vgs% ./ruby -vrdebug b.rb
ruby 1.9.0 (2008-04-28 revision 16234) [i686-linux]
Debug.rb
Emacs support available.

b.rb:1:def a
(rdb:1) l
[-4, 5] in b.rb
=> 1 def a
2 puts :a
3 end
4
5 a
(rdb:1) b 2
Set breakpoint 1 at b.rb:2
(rdb:1) c
Breakpoint 1, a at b.rb:2
b.rb:2: puts :a
(rdb:1) c
a
vgs%

Guy Decoux

ruby 1.9.0 (2008-04-28 revision 16234) [i686-linux]

Thanks for the info, I’ll run an update.

This is enough of a reason to choose ruby over python, IMO.

This thread is just about to begin to get funny. You could add
identifying comments on the right side, I suppose (assuming the debug
log lines are one-liners).

Using a tracer function would be another possibility.

Printing a backtrace from the Exception object often helps too.

It’s a pity ruby -rdebug doesn’t seem functional with ruby 1.9.

Eivind E.:

Eliminating stuff from a diff is often most easily done by storing
the diff in a file, editing out everything you want to keep, and then
doing patch -R < file_with_diffs_to_remove

Hey, that’s a very nice trick! Thanks a lot for sharing.

– Shot, a happy user of the vcscommand Vim plugin

On Wed, 30 Apr 2008, Joel VanderWerf wrote:

You can put debug code (invariant checks, and puts), flush with the left
margin (unindented). Then these lines can be grepped for with ^\w, more or
less. They also stand out when you scan the code visually.

Hokay, now that’s an idea! But lets generalize it a little…

What if we added a switch to ruby…

ruby -A regexp -R replacementString filename.rb

Which would have the meaning that all occurences of #regexp in the
code get replaced by replacementString. Where the default
replacementString is empty.

So for example, if you had ruby code “myfile.rb” like so…

def myfunc(a)
#PRECOND raise “Bad a” unless someexpression(a)

 do_stuff

 #DEBUG_LOG "a=#{a}, b=#{b}"

 do_otherstuff

 #POSTCOND raise "Didn't work" unless otherexpression

end

Then running it with an old version of ruby, or with the new version
the code would just work, the #PREBLAH would be treated as comments at
lex time and discarded.

def myfunc(a)
do_stuff
do_otherstuff
end

The code would run optimally fast.

Not run it with…

ruby -A PRECOND myfile.rb

The lexer would replace “#PRECOND” with “”, and the parser would see
it and evaluated it, leaving the POSTCOND commented out.

def myfunc(a)
raise “Bad a” unless someexpression(a)

 do_stuff

 do_otherstuff

end

It gets even better…

ruby -A “(PRE|POST)COND” -R “check_invariant;” myfile.rb

and the parser sees a full Design by Contract checking

def myfunc(a)
check_invariant;raise “Bad a” unless someexpression(a)

 do_stuff

 do_otherstuff

 check_invariant; raise "Didn't work" unless otherexpression

end

Or if you just want a debug logging trace…

ruby -A DEBUG_LOG -R “puts” myfile.rb
or
ruby -A DEBUG_LOG -R “STDERR.puts” myfile.rb
or
ruby -A DEBUG_LOG -R “$log_file.puts” -e
‘$log_file=open(“logfile.txt”,“w”)’ myfile.rb

Of course one can just create a wrapper on ruby that accepts any
options, but grabs the -A and -R options if present and any file
names, does a search and replace on the file “filename.rb”, writing
the result to a temporary file “_aspect_filename.rb” and then invoking
ruby with the rest of the parameters on “_aspect_filename.rb”.

The problem with that is the search and replace is just done on the
top level file, not on any files loaded or required.

Another problem is that a lot of care would have to be taken not to
get confused by # characters in all the many varieties of strings,
heredocs, regexps and character literals.

Hmm. Possibly one can search and replace loads and requires to do the
same. Hmm.

Anyway, any suggestions before I try a write the proof of concept
wrapper and then maybe make it an RCR?

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs