Make ruby-debug work better

If you’ve written Ruby, chances are you’ve had to use ruby-debug. You might’ve thought the experience sucked — especially the fact that the debugger defaults to a mode in which you have to use a keyword to get it to evaluate a statement. Lost? Here’s what I mean:

Say you start the debugger here:

1
2
result = resource[xml_obj.api_call_string].get
(rdb:1)

Then you want to take a look at the “xml_obj” variable. If this were (for instance) Python’s pdb, we’d just type “xml_obj” and hit return and be done with it. Not so in ruby-debug:

1
2
(rdb:1) xml_obj.api_call_string
*** Unknown command: "xml_obj.api_call_string".  Try "help".

This is because with default settings, the debugger needs a keyword (’p') to get it to actually evaluate your statement as Ruby and not a command to the debugger itself:

1
2
(rdb:1) p xml_obj.api_call_string
"documentService/documentsByCommunity"

That gets really tedious, really fast. The debugger’s help function (’help p’) will helpfully tell you that this is because the “autoeval” option is not enabled. If you’re thick like me, you won’t see this and you’ll just continue doing “p <whatever>” until you get so frustrated you drop what you’re doing one day and go hunt down a fix.

Here is that fix from inside your code:

1
2
require 'ruby-debug'
Debugger.settings[:autoeval] = true

You can also do this inside the debugger:

1
2
(rdb:1) set autoeval
autoeval is on.

Rails already does it via Rack middleware

You might be wondering why the debugging experience is different in Rails than in Ruby you’ve written elsewhere. I did too — remembering that this ‘p’ business isn’t necessary when I run the debugger as an option when I start up Mongrel in a Rails app. So I went digging for the code that Rails uses to set this stuff up. Those settings come from a piece of Rack middleware that lives in lib/rails/rack/debugger.rb. Here’s the class definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module Rails
  module Rack
    class Debugger
      def initialize(app)
        @app = app

        require_library_or_gem 'ruby-debug'
        ::Debugger.start
        ::Debugger.settings[:autoeval] = true if ::Debugger.respond_to?(:settings)
        puts "=> Debugger enabled"
      rescue Exception
        puts "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'"
        exit
      end

      def call(env)
        @app.call(env)
      end
    end
  end
end

For more info on how Rails uses Rack, this is a pretty handy page from the Rails guides.

3 Responses to “Make ruby-debug work better”

  1. [...] time on improvements I’ve found useful in using Ruby’s debugger. Friend Trevor Rosen beat me to the proverbial punch, however. Give his post a read first, I’ll [...]

Leave a Reply