Pry (and Friends) with Rails

Share this article

Pry (and Friends) with Rails
pryandrails

In my previous article, we looked at Pry, an extremely powerful alternative to the standard IRB shell that Ruby gives us.

For those who work with Rails, you will be happy to know that Pry has got your back. In this article, we look at the various ways Pry vastly improves our Rails workflow.

Do note that Pry works best with Ruby 1.9.3 and up.

Key Takeaways

  • Pry is a powerful alternative to the standard IRB shell that Ruby provides, offering improved workflow for Rails developers. It works best with Ruby 1.9.3 and up.
  • Installing Pry with Rails involves adding the pry-rails gem to the gemfile, or using Jazz Hands which includes pry-rails and other useful features like Awesome Print, Pry Doc, Pry Remote, Pry Debugger, and Pry Stack Explorer.
  • Pry provides tools to explore a Rails project without opening a single file, such as show-models to display the models a project contains, and show-routes to display routes.
  • Pry’s debugging capabilities are significant, allowing developers to introduce and debug errors directly from Pry. It also allows for the inspection of variables in scope and the editing of method definitions. The better_errors gem can make this process more efficient.

Getting the Sample Application

For our sample application, we would be using the application written for the Rails 3 tutorial by Michael Hartl.

To grab the application:

git clone git@github.com:benjamintanweihao/sample_app.git

Installing Pry with Rails

You could install pry on Rails by adding the pry-rails gem to your gemfile:

gem 'pry-rails', :group => :development

Or you could get that and other goodies with Jazz Hands.

group :development do
  gem 'jazz_hands'
end

Out of the box, Jazz Hands not only includes pry-rails, but it also includes other niceties such as:

  • Awesome Print
  • Pry Doc
  • Pry Remote
  • Pry Debugger
  • Pry Stack Explorer

Once you have got that settled, change back into the sample_app directory and install all the necessary dependencies:

bundle install

Setting up the database

rake db:schema:load

Note that some of you might need to prefix the above command with bundle exec.

One final thing before we proceed to the fun stuff: Create .pryrc in your home directory:

% touch ~/.pryrc

Fill it in with the editor of your choice:

Pry.config.editor = 'vim'

Launching Pry

… is trivial. Simply do a

rails c

and you’re greeted with a pry console:

% rails c
Loading development environment (Rails 3.2.16)

Frame number: 0/3
[1] sample_app »

Exploring a Rails project

Pry gives you a few tools to poke around a project without having to open a single file.

show-models

The first thing we’ll do is see what models the project contains. This is exactly what show-models tell you:

[1] sample_app »  show-models
Micropost
  id: integer
  content: string
  user_id: integer
  created_at: datetime
  updated_at: datetime
  belongs_to :user
Relationship
  id: integer
  follower_id: integer
  followed_id: integer
  created_at: datetime
  updated_at: datetime
  belongs_to :followed
  belongs_to :follower
User
  id: integer
  name: string
  email: string
  created_at: datetime
  updated_at: datetime
  password_digest: string
  remember_token: string
  admin: boolean
  has_many :followed_users (through :relationships)
  has_many :followers (through :reverse_relationships)
  has_many :microposts
  has_many :relationships
  has_many :reverse_relationships

Very awesome! Notice that the output has some very pretty syntax highlighting.

show-routes

rake routes is something I do pretty frequently. Sometimes, when I’m in the midst of a console session, it can be quite inconvenient and distracting to switch windows/tabs just to display the routes.

That is, until show-routes came along:

[2] sample_app »  show-routes
following_user GET    /users/:id/following(.:format) users#following
followers_user GET    /users/:id/followers(.:format) users#followers
         users GET    /users(.:format)               users#index
               POST   /users(.:format)               users#create
      new_user GET    /users/new(.:format)           users#new
     edit_user GET    /users/:id/edit(.:format)      users#edit
          user GET    /users/:id(.:format)           users#show
               PUT    /users/:id(.:format)           users#update
               DELETE /users/:id(.:format)           users#destroy
      sessions POST   /sessions(.:format)            sessions#create
   new_session GET    /sessions/new(.:format)        sessions#new
       session DELETE /sessions/:id(.:format)        sessions#destroy
    microposts POST   /microposts(.:format)          microposts#create
     micropost DELETE /microposts/:id(.:format)      microposts#destroy
 relationships POST   /relationships(.:format)       relationships#create
  relationship DELETE /relationships/:id(.:format)   relationships#destroy
          root        /                              static_pages#home
        signup        /signup(.:format)              users#new
        signin        /signin(.:format)              sessions#new
       signout DELETE /signout(.:format)             sessions#destroy
          help        /help(.:format)                static_pages#help
         about        /about(.:format)               static_pages#about
       contact        /contact(.:format)             static_pages#contact

show-routes has another really useful feature: For larger Rails projects, simply displaying all the routes would easily flood your screen and cause your eyes to water.

Let’s find out what else show-routes is capable of. Prefix the command with a ?):

[3] sample_app »  ? show-routes

From: /usr/local/var/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/pry-rails-0.3.2/lib/pry-rails/commands/show_routes.rb
Number of lines: 6

Usage: show-routes [-G]

show-routes displays the current Rails app's routes.

    -G, --grep      Filter output by regular expression
    -h, --help      Show this message.

So, if I wanted to recall whether it was sign_up or signup, I can do a quick filter:

[3] sample_app »  show-routes -G sign
        signup        /signup(.:format)              users#new
        signin        /signin(.:format)              sessions#new
       signout DELETE /signout(.:format)             sessions#destroy

To display all the POST actions:

[4] sample_app »  show-routes -G POST
               POST   /users(.:format)               users#create
      sessions POST   /sessions(.:format)            sessions#create
    microposts POST   /microposts(.:format)          microposts#create
 relationships POST   /relationships(.:format)       relationships#create

Awesome Printing is Awesome.

(Note: This is not part of pry-rails, but is installed with Jazz Hands. You can get awesome_print by installing the gem standalone, if needed.)

When you do Model.all, the result is usually an unintelligible mess. Here’s a sample of how awesome-print eases that pain (I went ahead and created some Micropost records):

[5] sample_app »  Micropost.all
  Micropost Load (0.2ms)  SELECT "microposts".* FROM "microposts" ORDER BY microposts.created_at DESC
=> [
  [0] #<Micropost:0x007ff7dcda7038> {
            :id => 2,
       :content => "Sure is! Wait till you combine it with Rails!",
       :user_id => 1,
    :created_at => Mon, 27 Jan 2014 15:13:35 UTC +00:00,
    :updated_at => Mon, 27 Jan 2014 15:13:35 UTC +00:00
  },
  [1] #<Micropost:0x007ff7dd66e770> {
            :id => 1,
       :content => "Hello! Isn't Pry awesome?",
       :user_id => 1,
    :created_at => Mon, 27 Jan 2014 15:13:21 UTC +00:00,
    :updated_at => Mon, 27 Jan 2014 15:13:21 UTC +00:00
  }
]

Once you are used to this beautifully formatted, color-coded output, you will never turn back to the plain old rails console ever again.

show-doc

Do not forget that the entire documentation is within easy reach:

[6] sample_app »  cd Array
[7] sample_app(../Array) »  show-doc each_cons

From: enum.c (C Method):
Owner: Enumerable
Visibility: public
Signature: each_cons(arg1)
Number of lines: 14

Iterates the given block for each array of consecutive <n>
elements.  If no block is given, returns an enumerator.

e.g.:
    (1..10).each_cons(3) { |a| p a }
    # outputs below
    [1, 2, 3]
    [2, 3, 4]
    [3, 4, 5]
    [4, 5, 6]
    [5, 6, 7]
    [6, 7, 8]
    [7, 8, 9]
    [8, 9, 10]

Debugging

Pry really shines is its debugging capabilities. Let’s purposely introduce a bug into our project directly from Pry.

First, navigate to the UsersController:

[8] sample_app »  cd UsersController
[9] sample_app(../UsersController) »

show-source

Recall that we can inspect the file source with the show-source command:

[10] sample_app(../UsersController) »  show-source

From: /Users/rambo/Desktop/sample_app/app/controllers/users_controller.rb @ line 1:
Class name: UsersController
Number of monkeypatches: 4. Use the `-a` option to display all available monkeypatches
Number of lines: 74

class UsersController < ApplicationController
  before_filter :signed_in_user,
                only: [:index, :edit, :update, :destroy, :following, :followers]
  before_filter :correct_user,   only: [:edit, :update]
  before_filter :admin_user,     only: :destroy

  def index
    @users = User.paginate(page: params[:page])
  end

  def show
    @user = User.find(params[:id])
    @microposts = @user.microposts.paginate(page: params[:page])
  end

  # Other code omitted ...
end

edit-method

Now, let’s introduce the bug in the index action:

[10] sample_app(../UsersController) »  edit index

Notice that vim (or whatever editor you configured previously) shows up, with the cursor directly at the start of the method definition.

Now, just add a raise at the bottom of the index action:

def index
  @users = User.paginate(page: params[:page])
  raise # <-- Add this
end

After you save and exit, you will be returned to the console.

Debugging with binding.pry

Obviously, when you navigate to http://localhost:3000/users, it will blow up.

Let’s assume you encounter some error in your app. Here are the steps which I usually take:

  • cd into the class
  • edit the offending method
  • add binding.pry

So let’s go back into our console, and do just that:

def index
  @users = User.paginate(page: params[:page])
  binding.pry
  raise
end

This time, navigate to http://localhost:3000/users. However, instead of blowing up, notice that the browser just hangs there.

Check your console window where your launched the rails server. You will notice that there’s another Pry session all prepared for you:

Frame number: 0/66

From: /Users/rambo/Desktop/sample_app/app/controllers/users_controller.rb @ line 9 UsersController#index:

     7: def index
     8:   @users = User.paginate(page: params[:page])
 =>  9:   binding.pry
    10:   raise
    11: end

[1] sample_app(#<UsersController>) »

In this session, you can easily examine all the variables that are in the scope.

We can inspect the contents of @users:

[3] sample_app(#<UsersController>) »  @users
=> [
  [0] #<User:0x007f847f108168> {
                 :id => 1,
               :name => "Benjamin Tan Wei Hao",
         :created_at => Mon, 27 Jan 2014 14:18:22 UTC +00:00,
         :updated_at => Mon, 27 Jan 2014 14:18:22 UTC +00:00,
              :admin => false
  }
]

Let’s try params:

[2] sample_app(#<UsersController>) »  params
=> {
      "action" => "index",
  "controller" => "users"
}

session works too:

[4] sample_app(#<UsersController>) »  session
=> {
   "session_id" => "812d9cfb949e795ed2fef78c2188fc0e",
  "_csrf_token" => "e+MnQKg2URyBEhkXdxpwcmJnyeRT5J+Tc1PGMvYpoU4="
}

Once done, you can go ahead and use edit method_name to remove binding.pry and the raise.

Also, remember to exit, otherwise the request would be blocked indefinitely.

Better Errors

Sometimes, you need binding.pry to poke around variables and trace methods. It is also a good way to impress your programmer friends/colleagues.

But when you are done with that, you would soon realise that it slowly becomes a hassle. Thankfully, there’s the better_errors gem that does away with all the ceremony.

Installation

group :development do
  gem "better_errors"
  gem "binding_of_caller"
end

As the README notes, do not place this under the production group.

I included the raise error again in UsersController#index. If you take a look at the browser, the usual Rails error page is replaced with something much, much, MUCH better:

img

Wrapping Up

Hopefully I have convinced you, once again, of the awesomeness of Pry. Maybe you’re even inspired to use some of the techniques here to improve your Rails workflow.

Happy Prying!

Frequently Asked Questions (FAQs) about Pry in Rails

How do I install Pry in Rails?

Installing Pry in Rails is a straightforward process. First, you need to add the gem to your Gemfile. You can do this by opening your Gemfile in a text editor and adding the following line: gem 'pry-rails'. After adding the line, save and close the file. Then, run bundle install in your terminal to install the gem. Once the installation is complete, you can use Pry in your Rails application.

What are the benefits of using Pry over IRB in Rails?

Pry offers several advantages over the default IRB console in Rails. It provides syntax highlighting, which makes it easier to read and understand the code. It also allows you to navigate through your code with shell-like cd and ls commands, making it more convenient to use. Additionally, Pry provides powerful introspection capabilities, allowing you to dive deep into your code and understand how it works.

How can I use Pry for debugging in Rails?

Pry can be a powerful tool for debugging in Rails. You can insert binding.pry into your code at the point where you want to pause execution. When your application reaches this point, it will open a Pry session in your terminal, allowing you to inspect variables, call methods, and step through your code.

Can I use Pry with Rails testing frameworks?

Yes, you can use Pry with Rails testing frameworks like RSpec and MiniTest. To do this, you need to require the Pry gem in your test helper file and insert binding.pry into your tests where you want to pause execution. This will allow you to inspect your test environment and debug your tests.

How can I customize Pry’s behavior in Rails?

Pry’s behavior can be customized by creating a .pryrc file in your home directory. In this file, you can define custom commands, set default options, and configure Pry’s appearance. For example, you can change the prompt, enable or disable certain plugins, and set default options for commands.

Can I use Pry to inspect Rails models and controllers?

Yes, you can use Pry to inspect Rails models and controllers. By inserting binding.pry into your models or controllers, you can pause execution and inspect the state of your application at that point. This can be particularly useful for understanding complex queries or debugging issues with your controllers.

How can I use Pry to step through code in Rails?

To step through code with Pry, you need to use the step command. When you hit a binding.pry in your code, you can type step into the Pry console to move to the next line of code. You can also use next to move to the next line without stepping into methods, and continue to resume execution until the next binding.pry.

Can I use Pry to edit code in Rails?

Yes, you can use Pry to edit code in Rails. The edit command allows you to open the current file in your text editor, make changes, and then continue execution with the updated code. This can be a powerful tool for debugging and development.

How can I use Pry to inspect Rails routes?

You can use Pry to inspect Rails routes by running rails routes in a Pry session. This will display a list of all your application’s routes, along with the corresponding controller actions. You can also use show-route to display information about a specific route.

Can I use Pry in production environments?

While it’s technically possible to use Pry in production environments, it’s generally not recommended. Using Pry in production can expose sensitive information and potentially disrupt your application. It’s best to use Pry in development and test environments, where it can help you debug and understand your code without risking your production data.

Benjamin Tan Wei HaoBenjamin Tan Wei Hao
View Author

Benjamin is a Software Engineer at EasyMile, Singapore where he spends most of his time wrangling data pipelines and automating all the things. He is the author of The Little Elixir and OTP Guidebook and Mastering Ruby Closures Book. Deathly afraid of being irrelevant, is always trying to catch up on his ever-growing reading list. He blogs, codes and tweets.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week