Published

A better Rails debugger: ruby-debug

Just a few days ago, Kent Sibilev quietly released an amazing little plugin with far reaching consequences: ruby-debug. This is a marked improvement over Ruby’s own rdebug. The major difference is that he removed the major slow down that impacted rdebug usability with Ruby on Rails so it is blazing fast.

Instead of using the Kernel#set_trace_func API, which makes it possible to implement a debugger in Ruby, but has a negative effect on the speed on your program execution, he uses a native extension with a new hook using the Ruby C API

For each trace call Ruby interpreter creates a Binding object, even though it is not being used most of the time. ruby-debug library moves most of the functionality of debug.rb to a native extension, this way significantly improving the execution of your program.

This means that watchpoints and the standard tracing facility are not supported, but I’m gladly giving that up for the comfort and speed. And if you are wondering how the speed is, that is really the difference between utter frustration each time you debug something to bliss!

Previously I covered some options for Debugging in Rails. This is going to become my preferred option by far, and I’m willing to bet this will become yours too. Why? Because you can see the source code of where you are, you can execute step while watching some or your variables, you can inspect of your variables (this you could do with breakpointer), you can use conditional breakpoints, you can get a list of expressions to be displayed every time you step. The downside compared to breakpointer? You can’t do it remotely, which in most instances, as best as I can tell, is not going to be a problem at all.

Installation

Ruby-debug comes as a gem so to install, just run:

sudo gem install ruby-debug

Make sure you chose the proper windows or ruby version depending on your platform.

Using ruby-debug

To use in your rails application, assuming you want this to only be available in development mode (this is not such a great idea to leave in in production mode, just in case you forget to remove the breakpoints, and also for performance reasons as I’ll explain in a bit)

In environement.rb add the following:

SCRIPT_LINES__ = {} if ENV['RAILS_ENV'] == 'development'

This line is important if you want to be able to see your source code. SCRIPT_LINES__ is an obscure feature of the ruby interpreter. If it is defined, it will store all loaded ruby file in a hash, which debug-ruby will use to display where you are in your source code. The only problem is that it can have some impact on performance, and worst of all, use up quite a bit of memory, which is not so good in production (hence the “if ENV[‘RAILS_ENV’] == ‘development'”). SCRIPT_LINES__ needs to be initialized as early as possible so it can capture all loaded ruby files.

I’ve been toying around with Eclipse for Ruby/RoR and was frustrated that I couldn’t debug using methods like you describe but with a full GUI. So I hacked something out today that allows me to use all the debugging in-line features of Eclipse on a live Rails app. Not sure if this is useful – or its speed could possibly be increased by using some of the code you describe?

It is almost equivalent, if I recall correctly, I was putting it there to get it as quickly as possible during initialization. Since it starts recording loaded files when SCRIPTLINES gets initialized. So

I say was doing that, because with the newest versions of ruby-debug, you are much better off running your app with rdebug anyway. And you don’t need this anymore. use “rdebug script/server webrick”

If you want to be sure that no debugger call ends up in your production version, yes.
A better practice, though, is to only add calls to “debugger” when troubleshooting, then remove them once you are done.
I’ve found that using grep (or your editor’s equivalent) before you commit to make sure you’ve removed everything is a good practice.

How well would it work to put the debugger call in a helper method or something like that? I know you’d start one level deeper in the stack, but you could just step out of the method call and be right back where you need to be…

That’s a possibility, but I’m afraid this may get old pretty quickly as this would break the display command, the source list command to quickly know where you are, and see some key variables right away.
Overall, being disciplined about removing calls to debugger when you are done tracking a bug is a practice that has worked for me and not let me down again (for that first few times…)

Looks like the latest version of ruby-debug is 0.9.3, so you may want to update your links or just change them to a link to [http://rubyforge.org/frs/?group\_id=1900&release\_id=11354](http://rubyforge.org/frs/?group_id=1900&release_id=11354) since it gets updated fairly often, it appears.

I’ve not seen these ampersand-hash-number-semicolon symbols before: are we really meant to use these, or is my browser doing something weird? (firefox in ubuntu and ie in windows both show this so i don’t think it is my browser)

woah…my last post translated the symbols into single quotes when it put the comment text on your page…so there is definitely some formatting weirdness going on with your page. Just in case you don’t know what i’m on about ( :o) ), the second code example window, which is introduced with the text “To add a breakpoint, you will need to use:”