How to debug Ruby Programs

K

Krishna Mohan

Hi,

I'm a newbee to Ruby, can any one you please suggest me ways to debug a
Ruby Program.

Regards,
Kittu.
 
P

Phillip Gawlowski

-----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 Program.
|
| Regards,
| Kittu.

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

- --
Phillip Gawlowski
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-----
 
K

Krishna Mohan

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

thanks for the reply.
 
F

Fred

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
 
P

Phillip Gawlowski

-----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 Gawlowski
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-----
 
E

Eivind Eklund

Hi,

I'm a newbee to Ruby, can any one you please suggest me ways to debug a
Ruby Program.

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

3. 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.

4. 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.
 
J

Joel VanderWerf

Eivind said:
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.
 
T

ThoML

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.
 
T

ts

ThoML said:
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
 
T

ThoML

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

Thanks for the info, I'll run an update.
 
J

John Carter

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 Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top