If you are a Ruby developer, you likely use binding.pry frequently for debugging Rails and Ruby projects. But do you know what pry and binding actually are? In this post, I will walk you through binding and pry, and demonstrate why pry is such a powerful tool for debugging.

What is Binding and how does binding.pry work?
Read the blog post about binding in Ruby here.
What is Pry?
Pry is a powerful REPL (Read-Evaluate-Print Loop) for the Ruby language. It is significantly more capable than the standard IRB. Pry is an invaluable tool for debugging and exploring your codebase.
Using Binding with Pry
Calling binding.pry is essentially “prying” into the current binding or context of the code from your terminal. When you place binding.pry in your code, the execution context is captured and a REPL session is opened at that exact line during runtime.
Interestingly, pry can be used on any Ruby object, not just a binding object.
Let’s try using pry with a string object (remember, everything is an object in Ruby):
2.6.3 :001 > require 'pry'
=> true
2.6.3 :002 > "sathia".pry
[1] pry("sathia")> upcase
=> "SATHIA"
[2] pry("sathia")>
In the example above, I am calling pry on a String object. Inside the Pry console, I call upcase. This works because I am now operating within the context of that specific String instance.
Pry offers many other features beyond simple debugging:
Source Code Browsing
You can inspect the source code of any class or method directly from the console:
[3] pry("sathia")> show-source Array
From: /Users/satyanarayan/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/pp.rb @ line 329:
Class name: Array
Number of monkeypatches: 2. Use the `-a` option to display all available monkeypatches
Number of lines: 13
class Array # :nodoc:
def pretty_print(q) # :nodoc:
q.group(1, '[', ']') {
q.seplist(self) {|v|
q.pp v
}
}
end
def pretty_print_cycle(q) # :nodoc:
q.text(empty? ? '[]' : '[...]')
end
end
[4] pry("sathia")>
Documentation Browsing
You don’t have to visit external Ruby documentation; you can browse it directly in your console.
Ensure the pry-doc gem is installed on your system. You can install it directly from the Pry console with the following command:
gem-install pry-doc
[11] pry(Array):1> show-doc join
From: array.c (C Method):
Owner: Array
Visibility: public
Signature: join(*arg1)
Number of lines: 12
Returns a string created by converting each element of the array to
a string, separated by the given separator.
If the separator is nil, it uses current $,.
If both the separator and $, are nil,
it uses an empty string.
[ "a", "b", "c" ].join #=> "abc"
[ "a", "b", "c" ].join("-") #=> "a-b-c"
For nested arrays, join is applied recursively:
[ "a", [1, 2, [:x, :y]], "b" ].join("-") #=> "a-1-2-x-y-b"
Navigating Classes and State
Pry provides commands like cd and ls to navigate objects and list their methods and variables.
2.6.3 :004 > pry
[1] pry(main)> cd Array
[2] pry(Array):1> ls
Object.methods: yaml_tag
Array.methods: [] try_convert
Array#methods:
& [] bsearch compact! difference eql? flatten join min prepend reject! rindex shift sort! to_h values_at
* []= bsearch_index concat dig fetch flatten! keep_if none? pretty_print repeated_combination rotate shuffle sort_by! to_s zip
+ all? clear count drop fill hash last one? pretty_print_cycle repeated_permutation rotate! shuffle! sum transpose |
- any? collect cycle drop_while filter include? length pack product replace sample size take union
<< append collect! delete each filter! index map permutation push reverse select slice take_while uniq
<=> assoc combination delete_at each_index find_index insert map! place rassoc reverse! select! slice! to_a uniq!
== at compact delete_if empty? first inspect max pop reject reverse_each shelljoin sort to_ary unshift
locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_
To list all instance variables, use ls -i. To see all available options for ls, use ls -h.
[10] pry(Array):1> ls -h
Usage: ls [-m|-M|-p|-pM] [-q|-v] [-c|-i] [Object]
ls [-g] [-l]
ls shows you which methods, constants and variables are accessible to Pry. By
default it shows you the local variables defined in the current shell, and any
public methods or instance variables defined on the current object.
...
Command History
You can list the history of commands used in your current session:
[3] pry(Array):1> hist
1: upcase
2: show-source String
3: show-source Array
4: show-doc Array
5: cd Array
6: show-doc
7: cd Array
8: show-doc join
9: gem-install pry-doc
10: cd Array
11: show-doc join
12: cd Array
13: ls
[4] pry(Array):1>
You can also use grep, tail, head, and replay with the hist command.
For example:
[4] pry(Array):1> hist --tail 3
12: cd Array
13: ls
14: hist
[5] pry(Array):1> hist --grep join
8: show-doc join
11: show-doc join
[6] pry(Array):1> hist --replay 8
...
Accessing the Shell
You can open a Linux shell directly from the Pry prompt:
2.5.0 :008 > pry
[1] pry(main)> shell-mode
pry main:/Users/satyanarayan/Documents $ .ls
Books complaint friends pdfs videos
pry main:/Users/satyanarayan/Documents $
This allows you to navigate the file system and perform other terminal tasks without leaving your debugging session.
Rails-Specific Features
If you use the pry-rails gem instead of the standard pry, you gain access to powerful commands like show-routes and show-models.
# In your Gemfile
gem 'pry-rails', group: :development
➜ events git:(master) ✗ rails c
[1] pry(main)> show-routes
Prefix Verb URI Pattern Controller#Action
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
...
[2] pry(main)> show-models
ContactDetail
id: integer
contactable_type: string
contactable_id: integer
user_id: integer
created_at: datetime
updated_at: datetime
belongs_to :contactable
belongs_to :user