To Debug or Not to Debug (with Pry)?
An aspiring programmer’s adventure with binding.pry
When I first started my journey at Flatiron, training to become a software engineer, I was putsing everything out onto IRB to debug my program. This worked well back when I was learning the basics of Ruby and object oriented programming, when the code was fairly simple.
A bit later into the course, however, debugging with IRB using puts proved to be a hassle as my code became more complex. This was especially true with my first solo project coming up, Country CLI — an app that lets its users view country facts by calling code.
As this project is considerably larger than most of the labs I’ve done on Learn, I couldn’t continue on the debugging path I was on. There was too much to copy and paste, too much to keep track of, and somewhere along the way I would select the incorrect information, which made it difficult to select the scope of the broken method I was trying to fix. As difficult as it was without Flatiron’s tests to guide me, in order to successfully code this project, I’d have to find a better way to debug and interact with my program…
Thankfully, I was introduced to Pry, specifically binding.pry, through the school’s lesson, Debugging with Pry. There, I learned that with Pry, I could debug simply by dropping binding.pry into my code. Unlike IRB, Pry intertwines with the code — there was no need to keep copying and pasting the information into the REPL because Pry learns any code before the line it was invoked on. And as for binding? Binding refers to the code within its current scope. Take for example, the following code snippet from my project:
def self.all
@@all
end
But wait, what is all this? I could inject binding.pry as below and check just that. Now that I’ve called Pry, binding has become the scope within my method, #self.all.
def self.all
@@all
binding.pry
end
After running the programming, I could see that a new REPL is opened.
16: def self.all
17: @@all
=> 18: binding.pry
19: end[1] pry(Country)>
Let’s see what the value of self and @@all is.
16: def self.all
17: @@all
=> 18: binding.pry
19: end[1] pry(Country)> self
=> Country
[2] pry(Country)> @@all
=> []
[3] pry(Country)>
There is is! self is referring to my Country class object, and @@all is Country’s class variable set to an array (and judging from the name, it’s safe to assume @@all will hold all instances of the Country class object). Easy peasy.
So how did I get started with Pry on my local environment? Learn’s IDE had everything set up, so once I moved editors, my first challenge with Country CLI was to learn how to do the setup on my own.
Here is how I installed Pry and got it running:
First, I opened my terminal and ran —
gem install pry
Once I had Pry installed, I could open it up on my Country CLI project.
In Country CLI, I created a file called Gemfile —
touch Gemfile
In Gemfile, I specified that I wanted the Pry gem provided graciously by the Ruby Gems website —
source "https://rubygems.org"git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }gem 'pry'
then —
bundle install
— in order to install the Pry gem specified in Gemfile. This created a new folder called Gemfile.lock which lists the gem version installed.
The last step was to require the gem in the file that I was trying to call it on. In this case, it was my environment.rb file located in the config folder where I specified all the files and gems needed to run Country CLI.
require 'pry'
And we’re ready to go!
A couple of important things that I noted while debugging:
- When there is an error, drop pry one line above the error. If the error is coming before Pry, my terminal will return the error message before it could open Pry. Pry will not work if I am trying to drop it further into the program — the error must be fixed before moving on!
- I must invoke the method I am attempting to Pry into. If the method is never called, Pry will just skip over it onto the next thing that is invoked!
Pry is a very powerful debugging tool and a huge asset within the Ruby community. When used properly, it is so much more convenient to use than putsing all my code out onto IRB. Though it could be confusing at first, I make sure to remember to invoke my method and that I’m not hitting any errors before Pry could activate! Using binding.pry, I was able to easily debug my Country CLI project and really dive in and understand my code. Though this is just one chapter in using Pry. I wonder what other options are opened up to Ruby developers through Pry?