How Binding.Pry Became My Best Friend

Danira Cortez
5 min readJun 21, 2020

Learning to Debug and Write Code with binding.pry

I was first introduced to binding.pry while attempting to complete the pre-work for Flatiron School’s Software Engineering Bootcamp. One of the labs gave an intro to binding.pry and explained how you could place it in your code in order to debug it. That sounded great, but I wasn’t quite sure how to use it. I would place the binding.pry in my code and when I would run my file it wouldn’t “hit” my pry. Although it was quite frustrating, I would continue to change where I placed my binding.pry and run it again and again until it finally hit it. It would take weeks of trial and error to get the hang of it and finally understand what I was doing!

So what exactly is binding.pry?

It wasn’t until recently that I learned that binding.pry is made up of two components and not just one magic phrase that solves all! Pry is a REPL, which stands for Read, Evaluate, Print, Loop. Like other REPLs, such as IRB, Pry takes the user’s input, evaluates it, and returns the result to the user. However, with pry this interactive programming environment allows the user to be able to enter into the code rather than having to copy and paste the code, like one would do with IRB. You might ask, “If pry goes into your code what does binding do then?”. Great question! According to ruby-doc.org “Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use.”, in other words binding makes values of variables, methods, and self available to you! Together, you are able to enter your code, access variables within your scope, and evaluate what your code is returning.

Read | Evaluate | Print | Loop

You mentioned scope, what is that?

Understanding scope goes hand in hand with binding.pry. A very simplified explanation would be that scope determines what you can see/access at a given time. Take the following for example, var is a local variable that can only be accessed within example_method. You can find the length of the array by calling .length on var. However, if var.length were on line 5 rather than line 3, you wouldn’t be able to access var since ruby doesn’t know what var is outside of the method.

1: def example_method
2: var = [index0, index1, index2]
3: var.length
4: end

Got the basics, what now?

First, you must install pry! Type ‘gem install pry’ in your terminal to install the pry gem. Next, at the top of your file type ‘require ‘pry’ ’, this will allow you to use pry in the file. Now, taking scope into consideration, place the binding.pry within your code. It’s important to remember that your code will run until it hits the binding.pry, anything after that, is not available. Placement depends on your code, ask yourself “Where am I getting the error message?”, “Is there a loop?”, “Do I have an if statement?”, and “What am I trying to find?”, the answers will help determine placement. For example, if you have an if/else statement and placed the binding.pry on line 6, when running your file you wouldn’t hit the binding.pry because var.length IS greater than 2, thus ruby would return “This is fine” and not continue to else.

1: def example_method
2: var = [index0, index1, index2]
3: if var.length > 2
4: puts "This is fine"
5: else
6: binding.pry
7: puts "Add more!"
8: end
9: end

Debugging and writing code

Binding.pry can be used when you get an error message or if what you are returning is something other than what you’re expecting. In the following example you are expecting to return the sum of num and 2. If you run the file you’d get a return value of 3. Since this is basic math you may have quickly figured out that num would have to be 1, if the sum of num and 2 is 3. This would be correct, however, the expected return value is actually 5! How? Why? Let’s take a look!

    1: def plus_two(num)
2: num + 2
3: num
=> 4: binding.pry
5: end
[1] pry(main)> num
=> 3
[2] pry(main)> num + 2
=> 5
[3] pry(main)>

Once we add our binding.pry and run the file, we will hit the pry and the terminal will display part of your code, where the binding.pry is, and pry. At this point we can check to see what num is by typing num. It returns the value of 3! If we type num + 2 we return the value of 5. The plus_two method is supposed to return 5 but is returning 3, why is that? If you look at line 3, you will see that we typed num, num is 3, so the way we wrote the method, we are asking for the value of num instead of the sum of num and 2! Let’s fix that!

1: def plus_two(num)
2: sum = num + 2
3: sum
4: end

We now have a method that returns the sum of num and 2! In the same way that we confirmed what the values and returns were, we can write code using binding.pry! I like to write a method with binding.pry inside of it, then check the values I have available to me. Using the values that I have (or need to create), I type in pry what I think should be in my method. This way as I am writing my code, I am able to see what it is returning in real time. I use this to guide myself towards the return value or function that I want for the method I am writing. Like with anything else, this will take time and practice, but the more you practice the easier it becomes!

--

--

Danira Cortez

Software Engineer | React, JavaScript, Ruby on Rails | Seeking job opportunities