
Debugging like a pro in Ruby
When I started learning to programming, I didn’t realise the importance of knowing good tools to debug your code.
Usually I was writing very small programs, and if something didn’t work, it was to look carefully at the code to figure out the problem. In the worst cases, I would put a lot of “puts” statement everywhere in my code, to print out the value of the variables, and that “technique” was all I needed to debug.
However, that way of debugging not always work, specially when you have a lot of code to debug, and you are not sure what’s failing and where to put the “puts”.
Luckily for us, there is two great tools that can help us to debug our Ruby code: pry and pry-nav.
Pry is a gem that allows you to stop your application when running, and inspect the value of variables. Pry-nav adds more functionality to pry, specifically it allows you to move forward in your code, line by line.
It’s easier to see how useful this is with an example. Let’s say that we need to debug the following code:
def find_the_max_positive(arr)
i = 0
the_max = 0 while i < arr.length
if the_max < arr[i]
the_max = arr[i]
i += 1
end
endreturn the_max
end
That function should find the max. number in an array of positive numbers. Sadly, the function gives the right result only sometimes. For example, here:
find_the_max_positive([1,12, 29])It will return 29, which is the right answer. However, here:
find_the_max_positive([47, 10, 25])Our code will hang and our application never ends! It’s time to use pry and pry-nav.
First we need to include them, so we do it:
require 'pry'
require 'pry-nav'Now, we can specify where we want our code to stop. We don’t know exactly where is the bug, so let’s set the stop point at the beginning of our function.
In order to tell pry that we want to stop, we need to add the following line to the point where we want it to stop:
binding.pySo, let’s add that line to our code and run it.
Once we run it, this is what we’ll see in the terminal:

Great! that means that now you are able to see the value all the variables. To do that, you only need to write the name of the variable in the terminal. Let’s print the value of arr:

Now, thanks to pry-nav, we can execute our code step by step. By typing “next”, the code will move forward to the next line. Let’s do it:

Great, now we can go step by step, inspecting the variables each time and making sure that they match what we expect.
Let’s type next a couple of times, to enter in the loop:

We are now inside the loop, and the variables i and max are what we expected. Let’s continue and type next until we execute the full loop once.
By the way, my advise when debugging is to write down what you expect the value of the variables to be, and then compare them with what they really are. If they don’t match your expectations, then there is the bug!

Perfect, so now max is 47 and i is 1, this is what we expected. Let’s type next once again (small exercise, what values should the variables have if this code worked fine?) and check the value of i:

Aha! Did you see what happen? After typing next, the if statement was checked, and it was false (because arr[1] is 10, and max is 47) and we came back to the if check (because there is no more code inside the loop), but the index variable, i, is still 1! So, as the code is now, it will again make the same check, which will be false again, and will come back to this if again, and so on. Do you see the bug here? we should increment i always, not only when we find a max number.
We can now leave pry. To do that, type !!! in the terminal.

Now let’s fix the code:
def find_the_max_positive(arr) i = 0
the_max = 0 while i < arr.length
if the_max < arr[i]
the_max = arr[i]
end
i += 1
endreturn the_max
end
If we now run this function (notice that we have removed the binding.pry line) passing the previous array, we will get the right answer. Yay!
This was a very small/simple example, but hopefully I’ve convinced you about how important is to learn how to debug, how much time it can save to you, and how good are pry and pry-nav!.
