IRB is a great tool and is perfect for experimenting with small code samples and testing out new ideas. It has some difficulty however when the code samples become a bit larger or you’d like to start an IRB session half-way through a method, for example.

Pry, in some sense, is IRB turned on its head. Instead of having to bring your code to a REPL session (as with IRB) you instead bring a REPL session to your code, see the following:

# test.rb require 'pry' class A def hello() puts "hello world!" end end a = A.new # start a REPL session binding.pry # program resumes here (after pry session) puts "program resumes here."

We then run ruby test.rb from the command line and the following REPL session begins:

Beginning Pry session for main pry(main)> a.hello hello world! => nil pry(main)> def a.goodbye pry(main)* puts "goodbye cruel world!" pry(main)* end => nil pry(main)> a.goodbye goodbye cruel world! => nil pry(main)> exit Ending Pry session for main program resumes here.

There are a few things to note from above:

The first is that local variables are available to a Pry session (locals are not available to an irb session when using `irb -r`).

The second is that when you end a Pry session it returns to the running program; this makes Pry particularly useful for debugging.

Debugging

Pry sits somewhere between using `puts` statements to debug and using a bona fide debugger. It effectively opens up an IRB-like session at the place it’s called and makes all the program state at that point available.

In the example below, the code (sans the `binding.pry`) works as required in Ruby 1.8 but in 1.9 it returns the wrong result – notably check_array([]) displays "ary has content" ; whereas we want it to output "ary is empty!" We start a Pry session right after the line b = *ary to try to determine the problem in Ruby 1.9:

def check_array(ary) b = *ary # invoking Pry here for debugging binding.pry if !b puts "ary is empty!" else puts "ary has content" end end check_array([])

When running the above code the following Pry session starts up:

Beginning Pry session for main pry(main)> show-method def check_array(ary) b = *ary binding.pry if !b puts "ary is empty!" else puts "ary has content" end end => nil pry(main)> b => [] pry(main)> test = *[] => [] pry(main)> b = !ary.empty? => false pry(main)> exit Ending Pry session for main ary is empty!

From above the first thing we do is display the code for the method we’re debugging – Pry’s `show-method` command does this.

We next experiment and find that the behaviour of *[] has changed in 1.9 (in 1.8 it returned nil ) and this must be the cause of our problems. We then come up with a new test b = !b.empty? and let the program continue (by typing `exit`) with this new value of b . It now outputs the expected result.

Note that any changes to state we make in a Pry session persist during the lifetime of the program. This fact also makes Pry useful for interactively modifying runtime state.

Interactively modifying runtime state

It may be convenient to open a Pry session in the middle of a running program. The example below is of a game where we are using Pry to increase the lunar lander’s fuel; we also do a bit of exploration of the runtime state to show off some features of Pry.

Beginning Pry session for # pry(#)> ls [:_, :_pry_,:@state, :@frame_counter, :@playgame] => nil pry(#)> cd @playgame Beginning Pry session for # pry(#):1> ls [:_, :_pry_, :@map, :@font, :@wind, :@objects, :@lander] => nil pry(#):1> cd @lander Beginning Pry session for # pry(#):2> @fuel = 300000 => 300000 pry(#):2> nesting Nesting status: -- 0. # (Pry top level) 1. # 2. # => nil pry(#):2> cd .. Ending Pry session for # => nil pry(#):1> ls --methods [:__binding_impl__, :draw, :initialize, :lander, :level, :map] => nil pry(#):1> cd map Beginning Pry session for # pry(#):2> ls [:_, :_pry_, :@nebula, :@nebula_theta, :@moonscape] => nil pry(#):2> exit-all Ending Pry session for # Ending Pry session for # Ending Pry session for #

From above, Pry makes it easy to navigate runtime state. You can pop in and out of objects, nesting sessions as deeply as you like. The `cd` and `ls` commands are provided to make this navigation seem familiar and natural.

Customizability

Pry is also easily customizable – you can trivially set the input for a Pry session to objects other than `Readline` and `$stdin`; and likewise set the output object to something other than `$stdout`.

Many other features of Pry can also be customized making Pry a perfect choice for implementing custom shells. See Customizing Pry for more information.

An IRB Alternative

Pry can be invoked from the command line using the `pry` executable. It can then be used as an alternative to IRB. Many of the IRB command line options are supported. Type `pry –help` at the command line for more information.

Conclusion

Pry is an IRB-alike that can be invoked at any time and anywhere in the program and on any receiver; it can also receive input from anywhere and send output to anywhere. The examples shown here illustrate just some of the functionality of Pry, read the Wiki for the full story.

Share this: Twitter

Facebook

Reddit

Like this: Like Loading... Related