Ruby Fundamentals: Using Pry for Debugging
Everybody makes mistakes and if you’re building software, you’ll make a lot of mistakes. Erring is an essential part of coding. It can teach us valuable lessons about patience and deepen our understanding of the languages that we work with everyday. One Ruby tool in particular allows us to test our assumptions directly in the console of your program.
Pry is a Ruby gem and an interactive REPL (Read, Evaluate, Print Loop). A REPL is a programming environment that takes user input, evaluates it and outputs the result to the user. Other commonly used REPLs like IRB require you to enter a whole new environment each time. Once in IRB you’ll have to re-type or copy and paste the code that you’re looking to work with. Once you terminate your session, any variables, methods, or solutions you’ve come up with will disappear.
Pry’s greatest strength is that it can be inserted directly into the lines of your program. Once inserted it allows you to freeze time (stop your program) to understand what is actually happening. This makes it an invaluable tool for debugging.
You can easily install pry by opening your terminal, navigating to the very top of your directory using “cd ~” and entering “gem install pry” into the command line of your terminal
Once installed, be sure to type require ‘pry’ at the top of any file that you’re looking to pry into. Once you’ve completed these steps you should be all set. Let’s jump in and see how it works.
Debugging with Pry
Above you’ll find an array of hashes called “animal_array”. Each animal is a leader of their own animal kingdom. We’re doing a report on the proud leaders of these kingdoms and want to know their average age. Getting this answer might seem simple, but imagine iterating through a far longer, more complex nested data type where you can’t easily see where the sought-after data lives. In, these cases, we won’t simply be able to count the ages by hand and get the average.
Let’s come up with some code to figure this out.
In the above code, we’re seeking to iterate through the array, sum the ages of the animals (age_summed) and then divide that summed number by the amount of elements in the given array to get the average age of these proud animal leaders.
As it stands, we get an error message that looks something like this:
This is a NoMethodError. NoMethodErrors occur when we attempt to call a method on a receiver that does not have that method defined. To fix this, we should dive into our code and understand exactly what exactly ‘animal’ is in our enumerable block. Pry to the rescue!
To use pry, we need to put ‘binding.pry’ directly before the line that caused the error. In this case, we need to put binding.pry before line 5, the line with ‘animal.age’.
Remember if you put binding.pry after the line that is causing the error, pry will not work because the program will break before it reaches it.
Woah! Notice anything cool? We just froze our program like Neo in the Matrix. Inserting pry into our code has stopped the program right before it breaks so that we can re-examine our assumptions and get to the bottom of this NoMethodError. First, let’s figure out what animal is in this block.
If we type animal into the command line, we see that animal is the first index (index 0) of our array. It is a hash containing the name, age, species, and sound of the first animal ruler. What happens when we try to call ‘animal.age’ again ?
No dice. But wait, if we want to get the value of the key/value pair containing age, we need to use the correct key. Here, we can see that “:age” is the correct key we should be calling in order to get age not “.age”. What happens if we try that?
We did it! We’ve accessed the age of the first animal leader by using pry to understand the data-type of the object in our block. We should change our file to reflect what we’ve just learned. But first, while we’re here, what if we wanted to find the oldest leader?
Experimenting with Pry
That’s right! We can create methods inside of our pry without having to write a new function in our file. We’ve just created a method that finds the oldest animal leader.
If we come up with a method that works, we can just copy and paste it into our code file. Now let’s get out of here before we get carried away. With the new insights we’ve gained, we can exit out of pry to make the changes in our code file. To exit out of pry simply type ‘exit’ in the command line. Remember that if you have multiple prys set up, this will only bring you to the next pry. If you want to get out of pry altogether, type either “!!!” or “exit!” into the command line.
Wrapping Up — The Power of Pry
As we’ve just seen here, provides us a valuable playground to debug our code, test our assumptions, and even write new code without relying too heavily on guesswork. Simply using “puts” to test code may work with simpler methods and data structures, but once things get complex, we’ll need to gain more insight into what exactly is going on. If we don’t get this insight, we’re likely to waste time blindly writing code. Think about all the things you could be doing with that extra time!