How to debug your rails app using pry-rails
Tags: ruby, rails, tooling, webdev
Published: 2020-12-21 08:10:26

# Introduction
Pry is a runtime developer console and IRB alternative with powerful introspection capabilities. Pry aims to be more than an IRB replacement. It is an attempt to bring REPL driven programming to the Ruby language.

# Key features
* Syntax highlighting
* Source browsing
* Source editing
* Breakpoints
* Method and property inspection of objects
* Runtime invocation

# Installation
To get started using Pry, simply include the gem 'pry-rails' and 'pry-doc' in your Gemfile, and bundle install! Now every time you boot your rails console you’ll have a Pry shell.

# Usage
To start using pry in our rails app, just type `rails console` and pry REPL(read-evaluate-print-loop) will be started.

## show-routes
will show all the routes in the rails app.

```ruby
show-routes
                                  Prefix Verb   URI Pattern                                                                                       Controller#Action
                                   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
                                         PATCH  /users/:id(.:format)                                                                              users#update
                                         PUT    /users/:id(.:format)                                                                              users#update
                                         DELETE /users/:id(.:format)                                                                              users#destroy
```

## show-models
will show all the models in the rails app.

```ruby
show-models
User
  id: integer
  email: string
  password: string
  created_at: datetime
  updated_at: datetime
```

## binding.pry
It will stop execution and start a REPL (read-evaluate-print-loop), allowing us to dynamically type Ruby code, which gets evaluated, and we can see the result.
We can acess all the local variables in that instance.

```ruby
def index
    @users = User.all
    binding.pry
end

Processing by UsersController#index as HTML
[1] pry(#<UsersController>)> @users
  User Load (0.2ms)  SELECT "users".* FROM "users"
  ↳ app/controllers/users_controller.rb:8:in `index'
=> [#<User:0x00007f7115564040
  id: 1,
  email: "Zeeshan1414@gmail.com",
  password: "[FILTERED]",
  created_at: Thu, 17 Dec 2020 11:59:07.235965000 UTC +00:00,
  updated_at: Thu, 17 Dec 2020 11:59:07.235965000 UTC +00:00>]
[2] pry(#<UsersController>)> exit
```

## cd
By using cd you can access classes, objects and methods as if they were folders.
```ruby
user = User.first
   (0.6ms)  SELECT sqlite_version(*)
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User:0x000055f751c41258
 id: 1,
 email: "Zeeshan1414@gmail.com",
 password: "[FILTERED]",
 created_at: Thu, 17 Dec 2020 11:59:07.235965000 UTC +00:00,
 updated_at: Thu, 17 Dec 2020 11:59:07.235965000 UTC +00:00>
[3] pry(main)> cd user
[4] pry(#<User>):1> self
=> #<User:0x000055f751c41258
 id: 1,
 email: "Zeeshan1414@gmail.com",
 password: "[FILTERED]",
 created_at: Thu, 17 Dec 2020 11:59:07.235965000 UTC +00:00,
 updated_at: Thu, 17 Dec 2020 11:59:07.235965000 UTC +00:00>
email
=> "Zeeshan1414@gmail.com"
[12] pry(#<User>):1> password
=> "password"
cd email
[15] pry("Zeeshan1414@gmail.com"):2>
```

## ls
It will list all the variables, objects and methods.
```ruby
[15] pry("Zeeshan1414@gmail.com"):2> ls
ActiveSupport::Dependencies::ZeitwerkIntegration::RequireDependency#methods: 
  require_dependency
Comparable#methods: <  <=  >  >=  between?  clamp
MessagePack::CoreExt#methods: to_msgpack
JSON::Ext::Generator::GeneratorMethods::String#methods: to_json_raw  to_json_raw_object
String#methods: 
  %                  delete_prefix!         lines             strip              
  *                  delete_suffix          ljust             strip!             
  +                  delete_suffix!         lstrip            strip_heredoc      
  +@                 demodulize             lstrip!           sub                
  -@                 downcase               match             sub!               
  <<                 downcase!              match?            succ               
  <=>                dump                   mb_chars          succ!              
  ==                 each_byte              next              sum                
  ===                each_char              next!             swapcase           
  =~                 each_codepoint         oct               swapcase!          
  []                 each_grapheme_cluster  ord               tableize           
  []=                each_line              parameterize      titlecase          
  acts_like_string?  empty?                 partition         titleize           
  as_json            encode                 pathmap
```

## help
Show a list of commands or information about a specific command.
```ruby
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
  !                  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-doc
to see documentation for methods or Objects you are not sure about.
```ruby
[54] pry(#<User>):1> show-doc valid?

From: /home/zeeshan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activerecord-6.1.0/lib/active_record/validations.rb:56:
Owner: ActiveRecord::Validations
Visibility: public
Signature: valid?(context=?)
Number of lines: 10

Runs all the validations within the specified context. Returns true if
no errors are found, false otherwise.

Aliased as #validate.

If the argument is false (default is nil), the context is set to :create if
{new_record?}[rdoc-ref:Persistence#new_record?] is true, and to :update if it is not.

\Validations with no :on option will run no matter the context. \Validations with
some :on option will only run in the specified context.
```

## find-method
for looking up methods/objects whose names you do not remember.
```ruby
[56] pry(#<User>):1> find-method as_json

#<Class:0x000055f7516ee7b0>#as_json
ActiveModel::Serializers::JSON
ActiveModel::Serializers::JSON#as_json
ActiveRecord::Delegation
ActiveRecord::Delegation#as_json
Enumerable
Enumerable#as_json
Exception
Exception#as_json
Object
Object#as_json
Struct
Struct#as_json
```
## show-source
to quickly see the method definitions of code you want to understand better.
`show method` can also be used.
```ruby
[57] pry(#<User>):1> show-source valid?

From: /home/zeeshan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activerecord-6.1.0/lib/active_record/validations.rb:56:
Owner: ActiveRecord::Validations
Visibility: public
Signature: valid?(context=?)
Number of lines: 5

def valid?(context = nil)
  context ||= default_validation_context
  output = super(context)
  errors.empty? && output
end
```

## edit
It opens the file in editor and take you to that line of method.
```ruby
[61] pry(#<User>):1> edit valid?
```
!['edit in pry-rails'](https://dev-to-uploads.s3.amazonaws.com/i/9h8yvvfhmjrb95kbte1z.png)

## .shell-command
By prepending a dot(.) before the command, we can use the shell command inside the pry REPL as well.
```
[3] pry(#<User>):1> .ls
app		 db	       node_modules	  Rakefile   vendor
babel.config.js  Gemfile       package.json	  README.md  yarn.lock
bin		 Gemfile.lock  postcss.config.js  storage
config		 lib	       public		  test
config.ru	 log	       q		  tmp
```

## exit-all
It will exit the pry REPL from the terminal.
```ruby
[6] pry(#<User>):1> exit-all
```

# References
* https://github.com/pry/pry/wiki
* http://railscasts.com/episodes/280-pry-with-rails
* https://medium.com/rubyinside/powering-your-ruby-rails-development-with-pry-3d5dbd2a8b80
* https://devhints.io/pry