6.7. Debugging

Debugging is another important aspect of developing Rails applications. When something goes wrong it's fundamental to be able to understand what exactly is happening, as well as evaluate expressions and easily move around within the code.

As a Microsoft developer, you are probably accustomed to the excellent debugging support offered by Visual Studio and .NET. Having programmed in both environments, I can confirm that the level of support and convenience for debugging offered by .NET was way beyond what the Ruby world had to offer.

Ruby In Steel, covered in Chapter 1, enables you to work with Rails in Visual Studio and provides a fast debugger called Cylon.

Fortunately, there have been many efforts to improve this situation and Rails 2.x really simplifies the process of debugging applications by taking advantage of the fast ruby-debug gem. To perform fast debugging in Rails, three things are required:

  1. ruby-debug needs to be installed.

  2. You need to specify a "breakpoint" where you want the debugging session to start.

  3. The Web server needs to load the debugger.

Let's start by installing the ruby-debug gem. Run the following:

gem install ruby-debug

Notice that I opted not to add this as a prerequisite in configenvironment.rb because it's a gem that's required for development purposes only.

Having installed ruby-debug, you can now place the method debugger anywhere you want in the application. Let's temporarily add it to the index action of the Articles controller before the finder:

# GET /articles
# GET /articles.xml
def index
  debugger
  @articles = Article.published.paginate(:page => params[:page], :order =>
"published_at DESC")

respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @articles }
  end
end

You need to load the debugger; so start Mongrel with the --debugger option as shown here:

C:projectslog> ruby script/server  --debugger
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails 2.2.2 application starting on http://0.0.0.0:3000
=> Debugger enabled
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready.  INT => stop (no restart).
** Mongrel 1.1.5 available at 0.0.0.0:3000
** Use CTRL-C to stop.

If you head over to http://localhost:3000 with your browser, the index action of the Articles controller will be invoked. The method debugger will then be executed, starting a debugging session in the command prompt window where you started the server:

C:projectslog> ruby script/server  --debugger
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails 2.2.2 application starting on http://0.0.0.0:3000
=> Debugger enabled
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready.  INT => stop (no restart).
** Mongrel 1.1.5 available at 0.0.0.0:3000
** Use CTRL-C to stop.
C:/projects/blog/app/controllers/articles_controller.rb:6
@articles = Article.published.paginate(:page => params[:page], :order =>
"published_at DESC")
(rdb:5)

The actual output obviously depends on how you formatted your code in the controller (for example, how many lines you use for your finders).

The cursor is positioned on the last (highlighted line); your debug shell (rdb) is ready to receive expressions to evaluate and commands to execute.

You could even step into an irb session, by simply running irb.

Meanwhile the page in the browser is idly waiting, having not yet rendered anything, because everything is frozen in time where you placed the debugger method. The line of code displayed in the debug shell is the current line (which hasn't been executed yet). It's the one immediately below debugger in the index action. The list command shows the code surrounding your current breakpoint:

(rdb:5) list
[1, 10] in C:/projects/blog/app/controllers/articles_controller.rb
   1  class ArticlesController < ApplicationController
   2    # GET /articles
   3    # GET /articles.xml
   4    def index
   5      debugger
=> 6      @articles = Article.published.paginate(:page => params[:page], :order
=> "published_at DESC")
   7
   8      respond_to do |format|
   9        format.html # index.html.erb
   10        format.xml  { render :xml => @articles }

If you want to evaluate the value of the params[:page] parameter you can do so simply by issuing:

(rdb:5) params[:page]
nil
Or p params[:page]

In this particular case, it's the front page so no page parameters were passed during the request. If you want to see what parameters do exist, you can evaluate the whole params hash:

(rdb:5) params
{"action"=>"index", "controller"=>"articles"}

Great! How about moving on to the next line? You do so with the next command:

(rdb:5) next


Processing ArticlesController#index (for 127.0.0.1 at 2009-01-28 12:25:39) [GET]

c:/projects/blog/app/controllers/articles_controller.rb:9
respond_to do |format|
(rdb:5) list
[3, 12] in C:/projects/blog/app/controllers/articles_controller.rb
   3    # GET /articles.xml
   4    def index
   5      debugger
   6      @articles = Article.published.paginate(:page => params[:page], :order
=> "published_at DESC")
   7
=> 8      respond_to do |format|
   9        format.html # index.html.erb
   10        format.xml  { render :xml => @articles }
   11      end
   12    end
(rdb:5)

With next you executed lines 6/7, and moved onto line 8 (which has yet to be interpreted). list showed you once again where you are. You can now try to evaluate @articles:

(rdb:5) @articles
[#<Article id: 4, title: "Oh hi!", body: "Hi there!

If don't know what %{
color:red}Rails% ...", published: true, published_at: "2008-07-20 03:52:00", cre
ated_at: "2008-07-16 22:56:33", updated_at: "2008-07-17 16:21:48">]

Again, the actual line numbers depend on your code formatting but you get the idea. Other important commands aside from list and next are step, up, and cont. step and up are roughly the equivalent of F11 and Shift+F11 in Visual Studio. You can exit rdb with exit. It's definitely a different approach from what you're used to, but it works quite well and you'll probably learn to appreciate its simplicity and flexibility.

Remember to remove the debugger line after you've experimented with it.

A complete list of commands and their meanings is available online at http://blog.nanorails.com/articles/2006/07/14/a-better-rails-debugger-ruby-debug.

Debugging from the Console

The two-fold process you are using is a bit tedious. You have to start the Web server, visit the page, and only then can you step into the debug shell. The process can be sped up simply by loading the debugger from within the console. Once you've started the console, you'll need to require 'ruby-debug.' At that point, you can send requests such as app.get '/articles/4' and be taken directly to the debugging session.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.206.112