こちらの記事で繰り返し同じデバッグを行うために、 binding.b
に引数を渡す方法を説明しました。
これを Controllerで実行しようとしたときに、
# GET /users/1
def show
+ binding.b(do: 'i ;; b @user.hoge')
+
+ @user.hoge
render json: @user
end
初回はきちんと以下のように User#hoge
にブレイクポイントが設置できたのですが、
Started GET "/users/1" for ::1 at 2023-07-07 20:59:15 +0900
Processing by UsersController#show as HTML
Parameters: {"id"=>"1"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/controllers/users_controller.rb:48:in `set_user'
[8, 17] in ~/git/sample-app/app/controllers/users_controller.rb
8| render json: @users
9| end
10|
11| # GET /users/1
12| def show
=> 13| binding.b(do: 'i ;; b @user.hoge')
14|
15| @user.hoge
16|
17| render json: @user
=>#0 UsersController#show at ~/git/sample-app/app/controllers/users_controller.rb:13
#1 ActionController::BasicImplicitRender#send_action(method="show", args=[]) at ~/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionpack-7.0.5/lib/action_controller/metal/basic_implicit_render.rb:6
# and 57 frames (use `bt' command for all frames)
(rdbg:#debugger) i
%self = #<UsersController:0x00000000014aa0>
@_action_name = "show"
@_lookup_context = #<ActionView::LookupContext:0x0000000111bbc5d0 @details_key=nil, @digest_cache=nil, @cache=true, @prefixes=["users", "application"], @details={:locale=>[:en], :formats=>[:html], :va...>
@_params = #<ActionController::Parameters {"controller"=>"users", "action"=>"show", "id"=>"1"} permitted: false>
@_request = #<ActionDispatch::Request GET "http://localhost:3000/users/1" for ::1>
@_response = #<ActionDispatch::Response:0x0000000111df4438 @mon_data=#<Monitor:0x000000010795e680>, @mon_data_owner_object_id=36520, @header={"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"0", ...>
@_response_body = nil
@_routes = nil
@user = #<User:0x000000010641ea40 id: 1, name: "user1", created_at: Mon, 12 Jun 2023 00:36:48.844679000 UTC +00:00, updated_at: Mon, 12 Jun 2023 00:36:48.844679000 UTC +00:00, admin: false>
(rdbg:#debugger) b @user.hoge
#0 BP - Method @user.hoge at /Users/kyntk/git/sample-app/app/models/user.rb:6
[1, 8] in ~/git/sample-app/app/models/user.rb
1| class User < ApplicationRecord
2| validates :name, presence: true, uniqueness: true
3| has_many :articles, dependent: :destroy
4|
5| def hoge
=> 6| puts 'fuga'
7| end
8| end
=>#0 User#hoge at ~/git/sample-app/app/models/user.rb:6
#1 UsersController#show at ~/git/sample-app/app/controllers/users_controller.rb:15
# and 58 frames (use `bt' command for all frames)
Stop by #0 BP - Method @user.hoge at /Users/kyntk/git/sample-app/app/models/user.rb:6
(rdbg)
2回目に実行してもブレイクポイントが刺さらないということが置きました。
解決方法
- 1. ブレイクポイントを設置する前に、ブレイクポイントを削除する
- 2.
b User#hoge
のようにブレイクポイントを設置する
解説
2回目以降でブレイクポイントが刺さらなかった時に以下のようなメッセージが出力されていました。
duplicated breakpoint: BP - Method user.hoge at /Users/kyntk/git/sample-app/app/models/user.rb:6
ブレイクポイントを設置したいファイル、行数に対してはすでにブレイクポイントが設置されているようです。
しかし、同じ場所であっても、インスタンス user
が異なるためブレイクポイントで処理が停止しないようです。
1. ブレイクポイントを設置する前に、ブレイクポイントを削除する
そのため、ブレイクポイントを設置する前に、前回のものを削除してあげると毎回刺さるようになりました。
# GET /users/1
def show
- binding.b(do: 'i ;; b @user.hoge')
+ binding.b(do: 'del 0 ;; i ;; b @user.hoge')
@user.hoge
render json: @user
end
今回は0番目のブレイクポイントしか削除していないですが、、binding.b(do: "del ;; i ;; b @user.hoge")
のようにdel
の引数を指定しないと、全てのブレイクポイントを削除することができます。
2. b User#hoge
のようにブレイクポイントを設置する
ブレイクポイントは @user.hoge
のような記法以外にも、行数を渡したり、User#hoge
のように記述する方法もあります。
* `b[reak] <line>`
* Set breakpoint on `<line>` at the current frame's file.
* `b[reak] <file>:<line>` or `<file> <line>`
* Set breakpoint on `<file>:<line>`.
* `b[reak] <class>#<name>`
* Set breakpoint on the method `<class>#<name>`.
* `b[reak] <expr>.<name>`
* Set breakpoint on the method `<expr>.<name>`.
これを用いることで、2回目以降のブレイクポイントの設置は同じく duplicated のメッセージが表示されるものの、ブレイクポイントで止まってくれるようになりました。
# GET /users/1
def show
- binding.b(do: 'i ;; b @user.hoge')
+ binding.b(do: 'i ;; b User#hoge')
@user.hoge
render json: @user
end