Article
Debug Your Rails App With ruby-debug
At the start of this year, I published a book through SitePoint titled Build Your Own Ruby On Rails Web Applications. You'll forgive me if I'm a little biased, but it is, I believe, still the best beginner's Rails book out there, despite the fact that many other books on Rails have been released since.
One of the best things about the Ruby on Rails framework is that it's undergoing constant change -- it's continually being improved and tweaked. Unfortunately, this change means that anyone who purchased my book when it was initially published will have been faced with a quandary over which version of Ruby to use:
- You could follow the book's advice and stick with Ruby 1.8.4. This would allow you to work your way happily through the book (including the chapter on debugging), but it would also mean that you wouldn't receive the benefits of the bug fixes and security updates that come with having an up-to-date installation of Ruby.
- Alternatively, you could upgrade to a more recent version of Ruby. Doing so, however, would have prevented you from using the breakpointer client -- a tool to which much of Chapter 11 is devoted.
At the time of the book's publication, the breakpointer client was the best tool available for debugging a Rails application. However, breakpointer is not compatible with the latest version of the Ruby programming language.
So what's a Rails developer to do?
In this article we'll look at an alternative debugging tool for debugging Rails applications (or any Ruby script, for that matter) while still remaining up-to-date with the latest version of the Ruby interpreter. This tool is even slated to be bundled with future releases of Rails.
The magic new tool to which I'm referring is called ruby-debug.
A quick warning: this isn't a beginners' article. I'll assume that you've either read my book, or have a solid understanding of how to develop a web application using Ruby on Rails. Ideally you'll have Rails installed and will be comfortable with using the Interactive Ruby (irb) shell. It will also help if you're familiar with shovell, the sample application used in the book; download the sample to play along at home (note: the download is 2.2MB in size).
What Broke Breakpointer?
Before we delve into the inner workings of ruby-debug, let's look briefly at why a tool as useful as breakpointer came to be incompatible with the language for which it was designed to be used.
The breakpoint library, of which the breakpointer client is a part, was developed and released to the public by Florian Gross. It was built on top of a Ruby extension called binding.of_caller, which relied on a bug in Ruby's implementation of trace calls. This bug, however, was fixed in Ruby 1.8.5! The result is that both the binding.of_caller extension and the breakpoint library became unusable. The library is also no longer being maintained, so it's effectively dead.
Say Hello to ruby-debug
Back in July of 2006, Kent Sibilev released the first version of ruby-debug, describing it as "a faster implementation of the standard debug.rb." Today, ruby-debug is the most viable option with regards to debugging Ruby scripts -- and that includes Rails applications.
While it would be beyond the scope of this article for me to explain how ruby-debug works its magic behind the scenes, it suffices to say that ruby-debug uses a natively compiled Ruby extension that's written in C. The result is that it performs amazingly well, even with very large Ruby scripts.
Comparing Feature Sets
As I described in the tutorial in my book, the breakpointer client allowed us to step into our application at run time and explore it from the command line. While the ruby-debug tool includes similar functionality, it goes way beyond what good old breakpointer had to offer.
Unlike breakpointer, which worked from a simple irb prompt, ruby-debug provides you with a more advanced shell, similar to that provided by GDB, the GNU debugger for the C programming language.
In this shell you can:
- Step forward and backward in your code.
- Execute and skip lines of code (without copying and pasting them from your code editor window).
- List the actual source context at which you've stopped your application.
- Step into
irbmode and make use of the same shell that's used by breakpointer (if you're someone who finds old habits difficult to shake).
Installing ruby-debug
The following steps will configure your system for debugging with ruby-debug.
First of all, we need to install the ruby-debug library. Since it's distributed as a RubyGems package, the installation is as easy as typing the following command:
$ sudo gem install ruby-debug -y
The install script will prompt you to indicate the platform on which you're installing the gem. If you're on a Mac or a Linux system, select option 1; if you're on a Windows machine, select option 2. The installation process should look similar to that shown in Figure 1.
![]()
Y is for Yes, Please!
By invoking the gem command with the -y switch, we instructed the utility to automatically install all other packages upon which ruby-debug depends. In this case, those packages include the ruby-debug-base package containing the actual debugger code; the ruby-debug package contains the CLI (command line interface).
With ruby-debug happily installed, we can now place some hooks in our Rails application. For this example, we'll use the completed shovell application from the book as an example of the process of debugging with ruby-debug. If you'd like to follow along with this example, you should download shovell, the sample application, before reading any further.
In Rails
Making a Rails application aware of ruby-debug is as simple as adding a line to the application's config/environments/development.rb file:
# config/environments/development.rb
require "ruby-debug"
It makes sense to make this change to our development environment (as compared to, say, config/environment.rb), as this is the preferred environment in which you should perform your debugging. The aim should be to replicate any errors that occur in other environments, so debugging should rarely occur in a testing or production environment.
ruby-debug is part of EdgeRails
Many developers like being on the bleeding edge, and are happy to develop their applications with a version of Rails that's not guaranteed to be as stable as the official release, in order to receive the very latest feature additions. This version of the framework is referred to as EdgeRails.
Explicitly adding ruby-debug to your application environment is unnecessary if you're running EdgeRails -- simply start the application server with the --debugger argument to load the ruby-debug library.
With this setting in place, you can fire up your application server from your Rails application's root folder:
$ ruby script/server
Figure 2 shows the console output that results when we start the Mongrel server.
![]()
Bricks and Mongrels Only
If your development environment makes use of an alternative server, such as lighttpd with FastCGI, you won't be able to use it as a debugging platform. You'll need to be running either WEBrick or Mongrel.
At first glance, the console output doesn't look much different from what we're used to seeing when we run this command. However, keep a close eye on this window as we progress through this exercise.
Patrick has been developing web applications for ten years. Founder and lead developer of the freshmeat.net software portal, he and his Rails consultancy and application development company,