[Ruby on Rails] Debug (binding.pry)

Target

Master how to use binding.pry

Development environment

ruby 2.5.7 Rails 5.2.4.3 OS: macOS Catalina

Premise

This time, I will explain with reference to an example that even implements the comment function for posts.

-Build login environment with devise -Posting function that only logged-in users can do -Post editing function (update, delete) -Comment function implementation

flow

1 What is debugging? 2 Install gem'pry-byebug' Used with 3 controller Used in 4 view

What is debugging?

Investigate the cause of the error (the error may not occur) and What you do to achieve the ideal behavior is called debugging.

When the application raises an error Basically, an error message is output. Check the error message, debug it, and resolve the cause of the error.

This time, I will introduce binding.pry, which is one of the methods.

Install gem'pry-byebug'

gemfile


gem 'pry-byebug'

Terminal


$ bundle install
Supplement [pry-byebug] Stop processing the program at the place where you added the description, It is a gem that can check the state at that time.

Used in controller

Describe the following in the place where you want to stop the processing.

python


binding.pry

Actual usage example ①

Terminal


  def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments
  end

If there is a description like the above, add it as follows.

Terminal


  def show
    binding.pry
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments
  end

Then launch the rails server. Then, when you move to the described page, the screen should freeze. Please return to the terminal in that state. Then it is as follows.

Terminal


    31: def show
 => 32:   binding.pry
    33:   @post = Post.find(params[:id])
    34:   @comment = Comment.new
    35:   @comments = @post.comments
    36: end

[1] pry(#<PostsController>)> 

In this state, type params after [1] pry (# )> and press Enter. You can see that id = 32 can be obtained as a parameter of post.

Terminal


    31: def show
 => 32:   binding.pry
    33:   @post = Post.find(params[:id])
    34:   @comment = Comment.new
    35:   @comments = @post.comments
    36: end

[1] pry(#<PostsController>)> params
=> <ActionController::Parameters {"controller"=>"posts", "action"=>"show", "id"=>"32"} permitted: false>
[2] pry(#<PostsController>)> 

Next, let's write according to the controller. Then I was able to get the data of id = 32.

Terminal


[1] pry(#<PostsController>)> params
=> <ActionController::Parameters {"controller"=>"posts", "action"=>"show", "id"=>"32"} permitted: false>
[2] pry(#<PostsController>)> Post.find(params[:id])
  Post Load (3.4ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ?  [["id", 32], ["LIMIT", 1]]
  ↳ (pry):2
=> #<Post:0x00007f16b08cfeb0
 id: 32,
 user_id: 2,
 title: "test",
 body: "test",
 created_at: Tue, 08 Sep 2020 06:36:21 UTC +00:00,
 updated_at: Tue, 08 Sep 2020 06:36:21 UTC +00:00,
 post_image_id: nil>
[3] pry(#<PostsController>)> 

If you want to continue to see the comments for this post, write as follows. Then, I was able to get the comment information associated with id = 32.

Terminal


[3] pry(#<PostsController>)> Post.find(params[:id]).comments
  CACHE Post Load (0.0ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ?  [["id", 32], ["LIMIT", 1]]
  ↳ (pry):3
  Comment Load (2.6ms)  SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 32]]
  ↳ app/controllers/posts_controller.rb:32
=> [#<Comment:0x00007f16b0af5398
  id: 9,
  user_id: 2,
  post_id: 32,
  comment: "",
  created_at: Thu, 17 Sep 2020 09:52:01 UTC +00:00,
  updated_at: Thu, 17 Sep 2020 09:52:01 UTC +00:00,
  score: 1>]
[4] pry(#<PostsController>)> 

If the parameters you were looking for are returned, you are successful. If it does not come back, the description is incorrect and needs to be reviewed.

  • To exit, type exit and then Enter.

Actual usage example ②

In ①, I put it at the top, but this time I will put it at the bottom.

Terminal


  def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments
    binding.pry
  end

Then launch the rails server. Then, when you move to the described page, the screen should freeze. Please return to the terminal in that state. Then it is as follows.

Terminal


    31: def show
    32:   @post = Post.find(params[:id])
    33:   @comment = Comment.new     
    34:   @comments = @post.comments
 => 35:   binding.pry
    36: end

If you write @post there, you will get the same result as the description in Post.find (params [: id]) above.

Terminal


[1] pry(#<PostsController>)> @post
=> #<Post:0x00007fc2b06fc870
 id: 32,
 user_id: 2,
 title: "test",
 body: "test",
 created_at: Tue, 08 Sep 2020 06:36:21 UTC +00:00,
 updated_at: Tue, 08 Sep 2020 06:36:21 UTC +00:00,
 post_image_id: nil>
[2] pry(#<PostsController>)> 

In this way, you can change the item you want to check depending on where you put binding.pry. It is also recommended to try various things.

  • To exit, type exit and then Enter.

Actual usage example ③

binding.pry can also be used in if statements. [2] Enter pry (# )> if @ post.nil? [2] Because the display changes to pry (# ) * Describe the contents of the if statement line by line.

python


[2] pry(#<PostsController>)> if @post.nil?
[2] pry(#<PostsController>)*   redirect_to new_post_path
[2] pry(#<PostsController>)* else  
[2] pry(#<PostsController>)*   @post
[2] pry(#<PostsController>)* end  
=> #<Post:0x00007fc2b06fc870
 id: 32,
 user_id: 2,
 title: "test",
 body: "test",
 created_at: Tue, 08 Sep 2020 06:36:21 UTC +00:00,
 updated_at: Tue, 08 Sep 2020 06:36:21 UTC +00:00,
 post_image_id: nil>
[3] pry(#<PostsController>)> 
  • To exit, type exit and then Enter.
  • If there are many displays, they will be displayed halfway, but you can get them by pressing Enter. To finish the acquisition, press q to finish.

Used in view

When using it in view, describe as follows in the place you want to check.

python


<% binding.pry %>

The usage is the same as controller. The timing to use is used when checking the contents of each statement.

Summary

binding.pry can significantly speed up development depending on how you use it. Especially for beginners, if they can learn early, it will be easier to understand. We recommend early learning.

Recommended Posts