How to debug Ruby Programs

Discussion in 'Ruby' started by Krishna Mohan, Apr 29, 2008.

  1. Hi,

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

    Regards,
    Kittu.
    --
    Posted via http://www.ruby-forum.com/.
    Krishna Mohan, Apr 29, 2008
    #1
    1. Advertising

  2. -----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-----
    Phillip Gawlowski, Apr 29, 2008
    #2
    1. Advertising

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

    thanks for the reply.
    --
    Posted via http://www.ruby-forum.com/.
    Krishna Mohan, Apr 29, 2008
    #3
  4. Krishna Mohan

    Fred Guest

    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
    Fred, Apr 29, 2008
    #4
  5. -----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-----
    Phillip Gawlowski, Apr 29, 2008
    #5
  6. On Tue, Apr 29, 2008 at 11:05 AM, Krishna Mohan
    <> wrote:
    >
    > 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.
    Eivind Eklund, Apr 29, 2008
    #6
  7. Eivind Eklund 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.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Apr 29, 2008
    #7
  8. Krishna Mohan

    ThoML Guest

    > 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.
    ThoML, Apr 29, 2008
    #8
  9. Krishna Mohan

    ts Guest

    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
    ts, Apr 29, 2008
    #9
  10. Krishna Mohan

    ThoML Guest

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

    Thanks for the info, I'll run an update.
    ThoML, Apr 29, 2008
    #10
  11. Krishna Mohan

    John Carter Guest

    Small tweak to ruby lexing to create optimal aspects / DbC /debugtraces.

    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 Carter Phone : (64)(3) 358 6639
    Tait Electronics Fax : (64)(3) 359 4632
    PO Box 1645 Christchurch Email :
    New Zealand
    John Carter, Apr 29, 2008
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    12
    Views:
    1,633
    Dave Thompson
    Jan 10, 2005
  2. Coca
    Replies:
    7
    Views:
    733
    Aidan Grey
    Aug 24, 2004
  3. Replies:
    18
    Views:
    618
    Dave Thompson
    Jan 10, 2005
  4. lone_eagle
    Replies:
    3
    Views:
    631
    psykeedelik
    May 26, 2009
  5. Casey Hawthorne
    Replies:
    14
    Views:
    444
Loading...

Share This Page