Skip to content

Commit 5292486

Browse files
authored
Enrich the introduction for debug gem (rails#43621)
1 parent a7320e6 commit 5292486

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

guides/source/debugging_rails_applications.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,173 @@ Rails 7 includes the `debug` gem in the `Gemfile` of new applications generated
304304
by CRuby. By default, it is ready in the `development` and `test` environments.
305305
Please check its [documentation](https://github.com/ruby/debug) for usage.
306306

307+
### Entering a Debugging Session
308+
309+
By default, a debugging session will start after the `debug` library is required, which happens when your app boots. But don't worry, the session won't interfere your program.
310+
311+
To enter the debugging session, you can use `binding.break` and its aliases: `binding.b` and `debugger`. The following examples will use `debugger`:
312+
313+
```rb
314+
class PostsController < ApplicationController
315+
before_action :set_post, only: %i[ show edit update destroy ]
316+
317+
# GET /posts or /posts.json
318+
def index
319+
@posts = Post.all
320+
debugger
321+
end
322+
# ...
323+
end
324+
```
325+
326+
Once your app evaluates the debugging statement, it'll enter the debugging session:
327+
328+
```rb
329+
Processing by PostsController#index as HTML
330+
[2, 11] in ~/projects/rails-guide-example/app/controllers/posts_controller.rb
331+
2| before_action :set_post, only: %i[ show edit update destroy ]
332+
3|
333+
4| # GET /posts or /posts.json
334+
5| def index
335+
6| @posts = Post.all
336+
=> 7| debugger
337+
8| end
338+
9|
339+
10| # GET /posts/1 or /posts/1.json
340+
11| def show
341+
=>#0 PostsController#index at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:7
342+
#1 ActionController::BasicImplicitRender#send_action(method="index", args=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal/basic_implicit_render.rb:6
343+
# and 72 frames (use `bt' command for all frames)
344+
(rdbg)
345+
```
346+
347+
### The Context
348+
349+
After entering the debugging session, you can type in Ruby code as you're in a Rails console or IRB.
350+
351+
```rb
352+
(rdbg) @posts # ruby
353+
[]
354+
(rdbg) self
355+
#<PostsController:0x0000000000aeb0>
356+
(rdbg)
357+
```
358+
359+
You can also use `p` or `pp` command to evaluate Ruby expressions (e.g. when a variable name conflicts with a debugger command).
360+
361+
```rb
362+
(rdbg) p headers # command
363+
=> {"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "X-Download-Options"=>"noopen", "X-Permitted-Cross-Domain-Policies"=>"none", "Referrer-Policy"=>"strict-origin-when-cross-origin"}
364+
(rdbg) pp headers # command
365+
{"X-Frame-Options"=>"SAMEORIGIN",
366+
"X-XSS-Protection"=>"1; mode=block",
367+
"X-Content-Type-Options"=>"nosniff",
368+
"X-Download-Options"=>"noopen",
369+
"X-Permitted-Cross-Domain-Policies"=>"none",
370+
"Referrer-Policy"=>"strict-origin-when-cross-origin"}
371+
(rdbg)
372+
```
373+
374+
Besides direct evaluation, debugger also helps you collect rich amount of information through different commands. Just to name a few here:
375+
376+
- `info` (or `i`) - Information about current frame.
377+
- `backtrace` (or `bt`) - Backtrace (with additional information).
378+
- `outline` (or `o`, `ls`) - Available methods, constants, local variables, and instance variables in the current scope.
379+
380+
#### The info command
381+
382+
It'll give you an overview of the values of local and instance variables that are visible from the current frame.
383+
384+
```rb
385+
(rdbg) info # command
386+
%self = #<PostsController:0x0000000000af78>
387+
@_action_has_layout = true
388+
@_action_name = "index"
389+
@_config = {}
390+
@_lookup_context = #<ActionView::LookupContext:0x00007fd91a037e38 @details_key=nil, @digest_cache=...
391+
@_request = #<ActionDispatch::Request GET "http://localhost:3000/posts" for 127.0.0.1>
392+
@_response = #<ActionDispatch::Response:0x00007fd91a03ea08 @mon_data=#<Monitor:0x00007fd91a03e8c8>...
393+
@_response_body = nil
394+
@_routes = nil
395+
@marked_for_same_origin_verification = true
396+
@posts = []
397+
@rendered_format = nil
398+
```
399+
400+
#### The backtrace command
401+
402+
When used without any options, it lists all the frames on the stack:
403+
404+
```rb
405+
=>#0 PostsController#index at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:7
406+
#1 ActionController::BasicImplicitRender#send_action(method="index", args=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal/basic_implicit_render.rb:6
407+
#2 AbstractController::Base#process_action(method_name="index", args=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/abstract_controller/base.rb:214
408+
#3 ActionController::Rendering#process_action(#arg_rest=nil) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal/rendering.rb:53
409+
#4 block in process_action at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/abstract_controller/callbacks.rb:221
410+
#5 block in run_callbacks at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activesupport-7.0.0.alpha2/lib/active_support/callbacks.rb:118
411+
#6 ActionText::Rendering::ClassMethods#with_renderer(renderer=#<PostsController:0x0000000000af78>) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actiontext-7.0.0.alpha2/lib/action_text/rendering.rb:20
412+
#7 block {|controller=#<PostsController:0x0000000000af78>, action=#<Proc:0x00007fd91985f1c0 /Users/st0012/...|} in <class:Engine> (4 levels) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actiontext-7.0.0.alpha2/lib/action_text/engine.rb:69
413+
#8 [C] BasicObject#instance_exec at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activesupport-7.0.0.alpha2/lib/active_support/callbacks.rb:127
414+
..... and more
415+
```
416+
417+
Every frame comes with:
418+
419+
- Frame identifier
420+
- Call location
421+
- Additional information (e.g. block or method arguments)
422+
423+
This will give you a great sense about what's happening in your app. However, you probably will notice that:
424+
425+
- There are too many frames (usually 50+ in a Rails app).
426+
- Most of the frames are from Rails or other libraries you use.
427+
428+
Don't worry, the `backtrace` command provides 2 options to help you filter frames:
429+
430+
- `backtrace [num]` - only show `num` numbers of frames, e.g. `backtrace 10` .
431+
- `backtrace /pattern/` - only show frames with identifier or location that matches the pattern, e.g. `backtrace /MyModel/`.
432+
433+
It's also possible to use these options together: `backtrace [num] /pattern/`.
434+
435+
#### The outline command
436+
437+
This command is similar to `pry` and `irb`'s `ls` command. It will show you what's accessible from you current scope, including:
438+
439+
- Local variables
440+
- Instance variables
441+
- Class variables
442+
- Methods & their sources
443+
- ...etc.
444+
445+
```rb
446+
ActiveSupport::Configurable#methods: config
447+
AbstractController::Base#methods:
448+
action_methods action_name action_name= available_action? controller_path inspect
449+
response_body
450+
ActionController::Metal#methods:
451+
content_type content_type= controller_name dispatch headers
452+
location location= media_type middleware_stack middleware_stack=
453+
middleware_stack? performed? request request= reset_session
454+
response response= response_body= response_code session
455+
set_request! set_response! status status= to_a
456+
ActionView::ViewPaths#methods:
457+
_prefixes any_templates? append_view_path details_for_lookup formats formats= locale
458+
locale= lookup_context prepend_view_path template_exists? view_paths
459+
AbstractController::Rendering#methods: view_assigns
460+
461+
# .....
462+
463+
PostsController#methods: create destroy edit index new show update
464+
instance variables:
465+
@_action_has_layout @_action_name @_config @_lookup_context @_request
466+
@_response @_response_body @_routes @marked_for_same_origin_verification @posts
467+
@rendered_format
468+
class variables: @@raise_on_missing_translations @@raise_on_open_redirects
469+
```
470+
471+
You can find more commands and configuration options from its [documentation](https://github.com/ruby/debug).
472+
473+
307474
Debugging with the `web-console` gem
308475
------------------------------------
309476

@@ -414,3 +581,4 @@ References
414581
----------
415582

416583
* [web-console Homepage](https://github.com/rails/web-console)
584+
* [debug homepage](https://github.com/ruby/debug)

0 commit comments

Comments
 (0)