Debugging strategies using binding.pry in Rails
19 May 2022
Something I had to get used to when switching to primarily Ruby on Rails development while working at Unabridged is debugging using
binding.pry instead of a step-debugger tool.
pry lets you stop the execution of running code, and inspect the values of all the in-scope variables at that point or run arbitrary code in that environment to figure out what's going wrong.
I was dealing with some tricky bugs the other day and asked my coworkers for strategies they use to more effectively work with
pry. Here are some of what we all came up with:
# Set the binding conditionally
This is helpful when you're processing a bunch of things and only one of them is causing trouble.
a_bunch_of_records.each do |record|
binding.pry if record.id == 1234
These move the stack frame
down respectively. Melinda told me about these methods which were exactly what I needed to solve my problem - the error was thrown in a method call based on what was getting passed in, but I needed to jump up the call stack to look at why that problematic data was getting passed in rather than what I should have had.
You can also keep going with
next, which goes to the next line, and
continue, which resumes normal execution until a pry is hit again.
tap a method
Drew's favorite method is using
tap on the result of a method.
do_some_stuff.tap do |result|
binding.pry if result.is_bad?
tap passes the result of your method to a block, like so:
so instead of taking
some_operation_to_debug and converting it to:
res = some_operation_to_debug
you can use
# Ways to stop bindings from being hit
# Set the binding unless you $skip_binding
Another variation on conditional binding, Nick likes to use
binding.pry unless $skip_binding
So that when he's done, he can do
$skip_binding = true and let execution continue instead of stopping the whole server in order to make the binding stop getting hit. (The
$ prefix on the variable makes it a global variable in Ruby).
Dre pointed out that Pry also has a built-in
disable-pry command which just continues without hitting any more prys.