MarkUs Blog

MarkUs Developers Blog About Their Project

Introduction to the Debugger gem

without comments

Though this post is probably coming a little late in the term to help anyone out with their Rails debugging right now, I’m hoping it might at least give a few people some insight onto how you can quickly debug in Rails without using an IDE, and also to newcomers to the Markus project who are also experiencing Rails for the first time.

Probably the first thing you’ll want to know, is how the debugger is included in the Rails project, and how you will have access to it. ┬áBy looking at the “Gemfile”, which specifies what “add-ons” our rails project is using, in the root of the project we see that the debugger gem is included for the Development and Test environments:

gem "debugger", :platforms => :mri_19

We need to include the debugger to have access to it, and if we check the config files for development and test under /config/environments, the lines:

require 'ruby-debug' if RUBY_VERSION == "1.8.7"
require 'debugger' if RUBY_VERSION > "1.9"

Show us that it will always be available for every file in these 2 environments. This enabled us to use the “debugger” command, to stop execution in any file, and then inspect the current state, modify variables, and run commands both under “rails server” and when running unit and functional tests.
For example, let’s put a “debugger” statement in the assignments controller:

# Called when editing assignments form is submitted (PUT).
def update
debugger
@assignment = Assignment.find_by_id(params[:id])
@assignments = Assignment.all
@sections = Section.all

When you now submit an update on the assignments page, you’ll notice that the page response stalls. If you check the console containing the rails server, you’ll see that you now have an interactive prompt:

/home/ioev/Projects/Markus/app/controllers/assignments_controller.rb:188
@assignment = Assignment.find_by_id(params[:id])
(rdb:1)

Here we see a listing of the line number the debugger stopped at, and the contents of the line as well. If you type “help” at the prompt, you’ll get a listing of all of the available commands:

(rdb:1) help
ruby-debug help v0.10.4
Type 'help ' for help on a specific command

Available commands:
backtrace delete enable help method putl set trace
break disable eval info next quit show undisplay
catch display exit irb p reload source up
condition down finish kill pp restart step var
continue edit frame list ps save thread where

The most useful commands to us right now, are “next, continue, list, p and pp” but you should experiment with the others as well.
“next” or “n” will execute the next line of code.
“continue” or “c” will continue to the end of execution, or to the next breakpoint. You can use this to end debugging (unless you’ve got a debugger statement in a loop, where you’ll just end up at the next iteration)
“list” will list the line the debugger is stopped on, and the lines surrounding it.
“p” and “pp” allow you to print out variables, or execute any ruby code.

So if we type “l” for list, we get:
(rdb:1) l
[183, 192] in /home/ioev/Projects/Markus/app/controllers/assignments_controller.rb
183 end
184
185 # Called when editing assignments form is submitted (PUT).
186 def update
187 debugger
=> 188 @assignment = Assignment.find_by_id(params[:id])
189 @assignments = Assignment.all
190 @sections = Section.all
191
192 if !params[:assignment].nil?

And say we want to print out the current value of params, which are the parameters passed in by the form, we can type “p params” or “pp params”:
(“pp” stands for “pretty print” and will print with a little bit more formatting that the regular print, which makes it really useful for arrays and hashes. “ps” is similar.)
(rdb:1) pp params
{"action"=>"update",
"id"=>"1",
"authenticity_token"=>"EN8RfAGUY/EfKNepI6VZqWPs9rUaOGSMlCWPCS9x5Y4=",
"_method"=>"put",
"assignment"=>
{"display_grader_names_to_students"=>"false",
"marking_scheme_type"=>"flexible",
"message"=>"Learn to use conditional statements, and loops.",
"remark_message"=>"",
"group_name_autogenerated"=>"0",
"repository_folder"=>"A1",
"remark_due_date"=>"",
"description"=>"Conditionals and Loops",
"submission_rule_attributes"=>{"id"=>"1", "type"=>"NoLateSubmissionRule"},
"allow_web_submits"=>"true",
"due_date"=>"2012-11-21 16:17",
"short_identifier"=>"A1",
"allow_remarks"=>"true",
"student_form_groups"=>"0"},
"controller"=>"assignments",
"utf8"=>"?",
"locale"=>"en"}

Since “debugger” is a command, you can also use conditionals to only activate the debugger only under certain conditions. For example:

debugger if variable.nil?

Which is really useful if you’re looping through a large set of data, and are having trouble with only one piece, this will help you narrow things down.
So now that you have an idea how to use the Rails debugger, I hope you never have to use a “puts” statement and search the console for the output ever again!
Good luck!

Written by Joey Perry

December 6th, 2012 at 11:24 pm

Leave a Reply