Ruby
Article

Pry: A Simple Start

By Vinoth

pry_logo (1)

A REPL – Read, Eval, Print, Loop, is an interactive shell for a programming language to evaluate expressions in the language. REPLs are a great way to learn a language, it’s syntax, and APIs.

Most programming languages have a REPL of its own or a community-built tool written for the same purpose. For Ruby, it’s IRB – Interactive Ruby Shell, that lets you play with Ruby in seconds and start experimenting with its features.

IRB comes bundled with Ruby and can be launched from the command line using the command irb. It provides command history, line editing, and executing Ruby programs from inside it. However, we aren’t going to talk about IRB today. Instead, I want to focus on an alternative, called pry, and what it brings to the table. We’ll see some nifty features that Pry is packed with today.

Installation

Obviously, before we can start messing with pry, we need to install it. Pry is a Ruby gem, so installing it is the same as installing any Ruby gem. Just type:

gem install pry pry-doc

We’ve added pry-doc to access the Ruby core documentation. To start pry, simply type pry after the gem is installed.

You can also make it part of your application’s dependencies by adding gem "pry" to your application’s Gemfile. Installing pry from within the application has its own benefits. In fact, there is a pry-rails gem that replaces the Rails console with Pry.

We won’t go into the Rails gem today, but I will focus on some of the best features of Pry and allow you to explore more on your own.

Exploring Documentation & Source

One of the most useful features available in Pry is the ability to explore the documentation and source code from within the shell. Pry makes it possible by fetching it from the source code during runtime. The command to show the documentation is show-doc accepts a method name. show-doc will easily work with ri and YARD documentation, and it also supports syntax highlighting and formatting. Let’s start playing with it.

When I type show-doc followed by the method name in the pry console, the documentation of the method is returned directly on the console:

pry(main)> show-doc Array#map

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: map()
Number of lines: 12

Invokes the given block once for each element of self.

Creates a new array containing the values returned by the block.

See also Enumerable#collect.

If no block is given, an Enumerator is returned instead.

   a = [ "a", "b", "c", "d" ]
   a.collect { |x| x + "!" }         #=> ["a!", "b!", "c!", "d!"]
   a.map.with_index { |x, i| x * i } #=> ["", "b", "cc", "ddd"]
   a                                 #=> ["a", "b", "c", "d"]

The result is quite self-explanatory, it returns the source of the documentation, it’s signature, the number of lines, and a description of the method that’s provided. You’ll notice that this is a C method, because I am using MRI. You’ll be happy to know that the core Pry commands work with any of the interpreters, including JRuby and Rubinius.

So, the method is part of the language core and written in C as we could gather from the result. We can go one up and view the source of this method directly from inside pry. Just type show-source followed by the method name:

pry(main)> show-source Array#map

From: array.c (C Method):
Owner: Array
Visibility: public
Number of lines: 13

static VALUE
rb_ary_collect(VALUE ary)
{
    long i;
    VALUE collect;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    collect = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
    rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
    }
    return collect;
}

There it is. The source code of the Array#map!

We can use show-method or show-source for any available method. Go on, try for some methods that you’ve been using.

Hooks

The next feature that we are going to see today are hooks. Hooks are nothing but callable methods that are associated with an event in Pry. Whenever an event occurs in Pry, a hook associated with it gets executed. Pry already has some events that we can “hook” into, like :before_session, :before_eval, and others. Let’s see and build a hook for one of these pre-existing events:

[1] pry(main)> Pry.hooks.add_hook(:after_read, "uphook") do |text, pry|
[1] pry(main)*   puts text.upcase
[1] pry(main)* end

Here we are creating a hook that runs after each statement is read by the shell and outputs the string back, turning it into uppercase. In order to test it, we have to start a new Pry session to load the hook:

[2] pry(main)> Pry.start
# New Session is started here
[1] pry(main)> "abc"
"ABC"
=> "abc"

As you can see, it capitalizes the inputted string. This is a simple use case of hooks, but you can make much more out of it. The Pry extensions use these a lot to deliver their great features. What’s more, you can even create your own events, and subsequently, your own hooks! Read more about creating your own custom events here

State Navigation

Pry provides a wonderful option to browse through objects, switching through contexts, and changing levels as if like a file system. Let’s see an example.

First, we’ll learn about a command called cd. cd <OBJECT_NAME> changes the context of the shell to the target object and you can check the available methods on that object, or go one level deep:

pry(main)> class Fruit
pry(main)* end
pry(main)> class Apple < Fruit
pry(main)* end

pry(main)> self
=> main
pry(main)> cd Fruit
pry(Fruit):1> self
=> Fruit
pry(Fruit):1> cd Apple
pry(Apple):2> self
=> Apple

As you can see, with each cd into an object the context of the shell shifts to the object, and you can keep on nesting as far as you want. Also, at any time you can quickly see how far you’ve nested and your nesting list using the command nesting.

pry(Apple):1> nesting
Nesting status:
--
0. main (Pry top level)
1. Fruit
2. Apple

pry(Apple):1> cd ..
pry(Fruit):1> self
=> Fruit
pry(Fruit):1> cd -
pry(Apple):2> self
=> Apple

Similar to the Unix cd command, to get to the parent object just type cd .. and to get to the previous object visited before the current object use cd -.

There are other useful commands that compliment the state navigation features of Pry, like ls – to show the list of methods, modules, and more. The find-method command is used to find a method’s functionality and what it does. The full feature set of state navigation commands is documented here

History

Another helpful feature of Pry is it’s history tracking. By default, when a pry session is started, Pry records the commands you’ve used in a history file which you can later inspect, analyze, or even replay. There are a number of configuration options provided by Pry out of the box around history tracking. By default, the history is stored in the /.pryhistory file, but you can easily change it by adding the below to your .pryrc file:

Pry.config.history.file = "~/.filenamehere"

Also, the history is loaded from the history file whenever a pry session starts and is saved to the file when the session ends. You can, however, override this behavior using the following configuration:

# To Disable the autoload
Pry.config.history.should_load = false

# To enable the autosave
Pry.config.history.should_save = false

Apart from directly working with the history file, you can also use the handy hist command which provides a set of flags that makes working with pry’s history a breeze. Typing the hist command prints out the entire stored history.

[9] pry(Rails):1> hist
1: hist
2: cd Rails
3: ls
4: cd Application
5: ls
6: show-method assets
7: cd ..
8: ls

You can, however, use the flags to further filter and inspect the history. Below are some of the few flags available.

To list all the commands that contain the word cd, use --grep:

[10] pry(Rails):1> hist --grep cd
2: cd Rails
4: cd Application
7: cd ..

To view the last 5 commands you’ve used, use the --tail option. The default number if the value is not passed is 10:

[11] pry(Rails):1> hist --tail 5
 6: show-method assets
 7: cd ..
 8: ls
 9: hist
10: hist --grep cd

There are more commands that are available in Pry’s hist interface, which are documented here. But, I’d like to show you one last cool flag of the hist command – replay. The replay flag allows you to execute the commands from the history, either a single one, or a range of commands by their line numbers. The usage is simple just do hist --replay X..Y:

[15] pry(main)> hist --replay 2..5
constants: API  Application  CommandsTasks  Configuration  Console  ConsoleMethods  Engine  Html  Info  InfoController  Initializable  MailersController  Paths  Rack  Railtie  VERSION  WelcomeController
ActiveSupport::Autoload#methods: autoload  autoload_at  autoload_under  autoloads  eager_autoload  eager_load!
Rails.methods:
  app_class  app_class=  application  application=  backtrace_cleaner  cache  cache=  configuration  env  env=  gem_version  groups  initialize!  initialized?  logger  logger=  public_path  root  version
instance variables: @_at_path  @_autoloads  @_eager_autoload  @_env  @_under_path  @app_class  @application  @cache  @logger  @parent_name
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
...

Conclusion

With that we have come to the conclusion of our tutorial. Pry is really a powerful replacement for the default IRB shell and works well in enhancing your existing workflow. We have only talked about few features of Pry, but it’s packed with much more, including step debugging (with the pry-debugger gem) and the ability to edit and reload files from within the REPL. We already have a tutorial to help get started with Pry, you can read it here and there is the comprehensive Pry wiki documentation page, which can be found here.

Thank you for reading and I hope it served your purposes.

More:
pry

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in Ruby, once a week, for free.