Rails - debugging with pry

Moin Moin,

debugging is one of the things a developer has to do most. One case is e.g when the customer is reporting a bug. Another one is when we are developing new software or features. Debugging is different in different languages. If you are coding Java, then it is pretty sure you are using Eclipse. It is offering a pretty good debugger inside the GUI. Developing JavaScript apps is less painless, since there are the great in-browser developer tools for Google Chrome or Mozilla Firefox.

Debugging in Rails is not a pain in the ass. The ruby-debug gem is quite good. You have to start the local server with -u or —debugger. The debugger is stopping the program execution where you set the ‘debugger’ method in your code. Inside the Rails log, there are then all the known debugger commands like ‘n’ for next, ‘c’ for continue and so on, available. In most cases this kind of ‘print_f’ debugging is sufficient. There are some caveats or even shortcomings. Sometimes the scope of the debugger is wrong and you have to stop/start the server to fix this.

Recently I stumbled upon an alternative for irb (the ruby interactive shell). It is called pry and can be found here. The tool is super awesome and I strongly recommend that you give it a try. Here is a good RailsCast from Ryan Bates.

The steps you have to do are simple:

 gem install pry pry-doc

In your Gemfile add:

 group :development do
   gem 'pry'
   ...
 end

Don’t forget to run bundle install afterwards.

Now set the following to any place in your code - here is some example code from an AR model:

 def printer_with_qraex_product
   printers = {}

   printer = select_printer
   total = printer.length

   printer = select_printer(true)
   printer.each do |p|
     cartridge = Cartridge.select('DISTINCT(qraexid)').where("printer_id=?
       and printer_group=?", p.id, group)[0]
     printers[p.name] = {qraexid: cartridge.qraexid}
   end
   binding.pry
   {:printer => printers, :total => total}
end

'binding.pry' is the same as you would use 'debugger'. It is stopping the execution BUT also opening the pry shell and showing the code around the binding to pry:

The cool thing is, that you now can access all the variables and methods in this scope:

 [1] pry(#<Printer>)> total
 => 2
 [2] pry(#<Printer>)> printer
 => [#<Printer id: 37693, name: "Color InkJet CP 1160">,
   #<Printer id: 37694, name: "Color InkJet CP 1700">]
 [3] pry(#<Printer>)>

You can continue the execution of the program by entering ‘exit-all’

Conclusion

pry is an awesome tool - not only for debugging but also (and mainly) for inspecting objects. Give it a try and you will see, that as here discussed, debugging is much more efficient and fun.

Published: May 26 2012