In this article we will show you how to debug your Rails applications using Pry. Pry is an excellent tool for debugging both Ruby and Rails applications that features powerful commands, syntax highlighting, and much more. Let's get started.

Installation

There are actually 2 gems to consider when installing pry. If you developing plain old Ruby apps or building on something like Sinatra, you'll want to use the pry gem. If you are building a Rails application, pry-rails will work better for you. First, we will show you how to install the pry-rails gem, then we will have a short section on the pry gem.

Installing pry-rails

The pry-rails gem offers up a number of extra capabilities. First, Pry is automatically enabled whenever you launch a rails console. Second, pry-rails provides a number of extra pieces of functionality, which we will cover in more detail below. To install the pry-rails gem, open up your Gemfile and add in the line listed below.

Gemfile:
 gem 'pry-rails', group: [:development, :test] 

You'll note that we only include Pry for the development and test environments. This is because we don't want Pry running in the production environment since it can cause issues.

Now run a bundle install to install the gem.

Terminal Commands:
 bundle install 

Now that Pry is installed for your Rails app, you can skip the next section since it primarily deals with non Rails applications.

Installing Pry For Non-Rails Applications

To install Pry when you aren't using Rails, you'll need to install the pry gem. This can be accomplished with the following command:

Terminal Commands:
 gem install pry 

Once the Pry gem is installed, you can launch directly into the Pry environment by using the pry console command.

Terminal Commands:
 pry 

You can include pry in your script with require 'pry':

example_script.rb:
 require 'pry' puts 'requiring pry' binding.pry 

The binding.pry command above initiates the pry console. You can also simply run your script with the pry command and skip the require 'pry' statement.

Basic Usage

Pry lets you instantly stop the execution of your app at any point, and debug your app within the scope of where you stopped. To stop execution you simple add a line that says:

 binding.pry 

You will then be dropped to a Pry prompt. For example:

 From: /home/richard/Documents/eCommerceExample/spec/controllers/categories_controller_spec.rb @ line 21 : 16: end 17: 18: include_examples 'sets the proper global variables' 19: 20: it "returns http success" do => 21: binding.pry 22: expect(response).to have_http_status(:success) 23: end 24: 25: it 'returns a list of categories' do 26: expect(assigns(:categories).size).to eq(1) [1] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> 

In the example above, we have inserted the binding.pry function at line 21 in the spec/controllers/categories_controller_spec.rb test featured in our eCommerce Site From Scratch Part 5: Images, Authentication, And More! article. We can then perform a number of actions. For instance, we can examine variables:

 [4] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> response.headers => {"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "Content-Type"=>"text/html; charset=utf-8"} [5] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> 

In the example above, we examined the headers of the response we got back from performing a GET show on our categories controller. You can examine any variable in your scope, for example, I can look at the instance variable @categories that is returned and check whether it is what I expected it to be:

 [5] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> assigns(:categories) => [#<Category:0x000000055d13a8 id: 1, slug: nil, name: "Beauty, Movies & Industrial", deleted_at: nil, created_at: Thu, 03 Nov 2016 00:46:31 UTC +00:00, updated_at: Thu, 03 Nov 2016 00:46:31 UTC +00:00>] [6] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> 

Note that you can exit pry at any time by using the exit-all command. You can also exit completely out of Ruby with the exit! command. Keep this in mind as we move forward.

 [12] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> exit-all 

Moving on, we can change scope, for example:

 [40] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> cd Category [41] pry(Category):1> ls --m --grep ordered Category.methods: ordered [42] pry(Category):1> 

In the code above, we changed scope to the category model, we then performed an ls --m --grep ordered to find the ordered method. The --m parameter stands for method. The --grep parameter filters our results to the specified string. We can then show the method using show-method:

 [42] pry(Category):1> show-method ordered From: /home/richard/Documents/eCommerceExample/app/models/concerns/ordered.rb @ line 3: Owner: #<Class:Category(id: integer, slug: string, name: string, deleted_at: datetime, created_at: datetime, updated_at: datetime)> Visibility: public Number of lines: 3 def self.ordered where(deleted_at: nil).order(name: :asc) end [43] pry(Category):1> 

In the above code you'll see that we listed the source to the .ordered method. You can also temporarily change the method. For example:

 [43] pry(Category):1> def self.ordered [43] pry(Category):1* puts 'not implemented' [43] pry(Category):1* end => :ordered [44] pry(Category):1> cd .. [45] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> Category.ordered not implemented => nil 

Here, we changed the .ordered method to print 'not implemented'. We then switched back to the parent scope and called .ordered, which printed 'not implemented'. Note that you don't have to switch to the parent scope, you could have just as easily called .ordered directly:

 [47] pry(Category):1> ordered not implemented => nil 

You can also use an editor to make more complex changes, first set the default editor you wish to use:

 [2] pry(main)> Pry.config.editor = 'vim' => "vim" 

Now we can use the edit method to edit the code in our favorite editor:

 6] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> cd Category [8] pry(Category):1> edit ordered 

The vim editor will now open, allowing you to more easily edit the method.

If you are deep within your program, you can use nesting and jump-to easily get back out. For example:

 [52] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> cd Category/ordered not implemented [53] pry(nil):2> nesting Nesting status: -- 0. #<RSpec::ExampleGroups::CategoriesController::GETShow> (Pry top level) 1. Category 2. nil [54] pry(nil):2> jump-to 0 [56] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> 

In the example above, we switched scope to Category#ordered, then we used jump-to to switch back to the parent scope.

If an error occurred, you can also show the most recent stacktrace with wtf?:

 [17] pry(Category):1> raise 'foobar' RuntimeError: foobar from (pry):13:in `__binding__' [18] pry(Category):1> wtf? Exception: RuntimeError: foobar -- 0: (pry):13:in `__binding__' 1: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval' 2: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby' 3: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line' 4: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval' 5: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch' 6: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval' 7: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch' 8: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval' 9: /home/richard/.rvm/gems/ruby-2.3.1/gems/pry-0.10.4/lib/pry/repl.rb:77:in `block in repl' [19] pry(Category):1> 

You can enter shell mode with shell-mode. For example:

 [20] pry(Category):1> shell-mode pry Category:/home/richard/Documents/eCommerceExample $ 

From there you can run shell commands by prefixing the command with a ., for example:

 pry Category:/home/richard/Documents/eCommerceExample $ .ls app bin config config.ru db Gemfile Gemfile.lock lib log public Rakefile README.md spec test tmp vendor pry Category:home/richard/Documents/eCommerceExample $ .cat config.ru # This file is used by Rack-based servers to start the application. require_relative 'config/environment' run Rails.application pry Category:/home/richard/Documents/eCommerceExample $ 

Rails Specific Methods

You can show a list of your models with show-models, for example:

 [2] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> show-models ActiveRecord::SchemaMigration version: string ApplicationRecord Table doesn't exist Category id: integer slug: string name: string deleted_at: datetime created_at: datetime updated_at: datetime has_many :products Product id: integer category_id: integer slug: string name: string brand: string description: text price: decimal deleted_at: datetime created_at: datetime updated_at: datetime image_file_name: string image_content_type: string image_file_size: integer image_updated_at: datetime belongs_to :category User id: integer email: string encrypted_password: string reset_password_token: string reset_password_sent_at: datetime remember_created_at: datetime sign_in_count: integer current_sign_in_at: datetime last_sign_in_at: datetime current_sign_in_ip: string last_sign_in_ip: string created_at: datetime updated_at: datetime 

You can also show an individual model with show-model, for example:

 [3] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> show-model User User id: integer email: string encrypted_password: string reset_password_token: string reset_password_sent_at: datetime remember_created_at: datetime sign_in_count: integer current_sign_in_at: datetime last_sign_in_at: datetime current_sign_in_ip: string last_sign_in_ip: string created_at: datetime updated_at: datetime [4] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> 

You can show the rails routes with show-routes, for example:

 [5] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> show-routes Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PATCH /users(.:format) devise/registrations#update PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy root GET / home#show categories GET /categories(.:format) categories#index category GET /categories/:id(.:format) categories#show product GET /products/:id(.:format) products#show search_results GET /search_results(.:format) search_results#index [6] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> 

You can find the routes for a given controller with find-route, for example:

 [9] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> find-route CategoriesController Routes for CategoriesController -- index GET /categories(.:format) [categories] show GET /categories/:id(.:format) [category] 

You can also find a controller and method based on a specified path using recognize-path, for example:

 [10] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> recognize-path / {:controller=>"home", :action=>"show"} 

To get help, simply type help at the Pry prompt. The full list of commands for Pry 0.10.4 is listed below.

 [11] pry(#<RSpec::ExampleGroups::CategoriesController::GETShow>)> help Help help Show a list of commands or information about a specific command. Context cd Move into a new context (object or scope). find-method Recursively search for a method within a class/module or the current namespace. ls Show the list of vars and methods in the current scope. pry-backtrace Show the backtrace for the pry session. raise-up Raise an exception out of the current pry instance. reset Reset the repl to a clean state. watch Watch the value of an expression and print a notification whenever it changes. whereami Show code surrounding the current context. wtf? Show the backtrace of the most recent exception. Editing /^\s*!\s*$/ Clear the input buffer. amend-line Amend a line of input in multi-line mode. edit Invoke the default editor on a file. hist Show and replay readline history. play Playback a string variable, method, line, or file as input. show-input Show the contents of the input buffer for the current multi-line expression. Introspection ri View ri documentation. show-doc Show the documentation for a method or class. show-source Show the source for a method or class. stat View method information and set _file_ and _dir_ locals. Gems gem-cd Change working directory to specified gem's directory. gem-install Install a gem and refresh the gem cache. gem-list List and search installed gems. gem-open Opens the working directory of the gem in your editor. Commands import-set Import a pry command set. install-command Install a disabled command. Aliases !!! Alias for `exit-program` [email protected] Alias for `exit-all` $ Alias for `show-source` ? Alias for `show-doc` @ Alias for `whereami` clipit Alias for `gist --clip` file-mode Alias for `shell-mode` find-routes Alias for `find-route` history Alias for `hist` quit Alias for `exit` quit-program Alias for `exit-program` reload-method Alias for `reload-code` show-method Alias for `show-source` Input and output .<shell command> All text following a '.' is forwarded to the shell. cat Show code from a file, pry's input buffer, or the last exception. change-inspector Change the current inspector proc. change-prompt Change the current prompt. fix-indent Correct the indentation for contents of the input buffer list-inspectors List the inspector procs available for use. list-prompts List the prompts available for use. save-file Export to a file using content from the repl. shell-mode Toggle shell mode. bring in pwd prompt and file completion. Misc gist Upload code, docs, history to https://gist.github.com/. pry-version Show pry version. reload-code Reload the source file that contains the specified code object. toggle-color Toggle syntax highlighting. Navigating pry !pry Start a pry session on current self. disable-pry Stops all future calls to pry and exits the current session. exit Pop the previous binding. exit-all End the current pry session. exit-program End the current program. jump-to Jump to a binding further up the stack. nesting Show nesting information. switch-to Start a new subsession on a binding in the current stack. Rails find-route See which urls match a given controller. recognize-path See which route matches a url. show-middleware Show all middleware (that rails knows about). show-model Show the given model. show-models Show all models. show-routes Show all routes in match order. Prompts simple-prompt Toggle the simple prompt. 

This is just scratching the surface of what Pry can do. Pry also features a robust plugin system and there are a number of plugins you can use. I hope that you enjoyed this brief introduction to Pry. If you have any questions or comments, please feel free to leave a comment below. Thanks for reading!

Resources