The `debug` helper will return a \<pre> tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:
Alternatively, calling `to_yaml` on any object converts it to YAML. You can pass this converted object into the `simple_format` helper method to format the output. This is how `debug` does its magic.
Another useful method for displaying object values is `inspect`, especially when working with arrays or hashes. This will print the object value as a string. For example:
TIP: The default Rails log level is `:debug`. However, it is set to `:info` for the `production` environment in the default generated `config/environments/production.rb`.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XLveDrKzF1SwaiNRPTaMtkrsTzedtebPPkmxEFIU0ordLjICSnXsSNfrdMa4ccyBjuGwnnEiQhEoMN6H1Gtz3A==", "article"=>{"title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs.", "published"=>"0"}, "commit"=>"Create Article"}
New article: {"id"=>nil, "title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs.", "published"=>false, "created_at"=>nil, "updated_at"=>nil}
Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels to avoid filling your production logs with useless trivia.
When looking at database query output in logs, it may not be immediately clear why multiple database queries are triggered when a single method is called:
After running `ActiveRecord.verbose_query_logs = true` in the `bin/rails console` session to enable verbose query logs and running the method again, it becomes obvious what single line of code is generating all these discrete database calls:
Below each database statement you can see arrows pointing to the specific source filename (and line number) of the method that resulted in a database call. This can help you identify and address performance problems caused by N+1 queries: single database queries that generates multiple additional queries.
WARNING: We recommend against using this setting in production environments. It relies on Ruby's `Kernel#caller` method which tends to allocate a lot of memory in order to generate stacktraces of method calls. Use query log tags (see below) instead.
INFO: This section was written by [Jon Cairns at a Stack Overflow answer](https://stackoverflow.com/questions/16546730/logging-in-rails-is-there-any-performance-hit/16546935#16546935)
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 with your application.
#1 ActionController::BasicImplicitRender#send_action(method="index", args=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-8.0.0.alpha/lib/action_controller/metal/basic_implicit_render.rb:6
You can exit the debugging session at any time and continue your application execution with the `continue` (or `c`) command. Or, to exit both the debugging session and your application, use the `quit` (or `q`) command.
#1 ActionController::BasicImplicitRender#send_action(method="index", args=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-2.0.alpha/lib/action_controller/metal/basic_implicit_render.rb:6
#2 AbstractController::Base#process_action(method_name="index", args=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-8.0.0.alpha/lib/abstract_controller/base.rb:214
#3 ActionController::Rendering#process_action(#arg_rest=nil) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-8.0.0.alpha/lib/action_controller/metal/rendering.rb:53
#4 block in process_action at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-8.0.0.alpha/lib/abstract_controller/callbacks.rb:221
#5 block in run_callbacks at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activesupport-8.0.0.alpha/lib/active_support/callbacks.rb:118
#6 ActionText::Rendering::ClassMethods#with_renderer(renderer=#<PostsController:0x0000000000af78>) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actiontext-8.0.0.alpha/lib/action_text/rendering.rb:20
#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-8.0.0.alpha/lib/action_text/engine.rb:69
#8 [C] BasicObject#instance_exec at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activesupport-8.0.0.alpha/lib/active_support/callbacks.rb:127
There are many ways to insert and trigger a breakpoint in the debugger. In addition to adding debugging statements (e.g. `debugger`) directly in your code, you can also insert breakpoints with commands:
=>#0 PostsController#create at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:25
#1 ActionController::BasicImplicitRender#send_action(method="create", 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
# and 72 frames (use `bt' command for all frames)
(rdbg) b 28 # break command
#0 BP - Line /Users/st0012/projects/rails-guide-example/app/controllers/posts_controller.rb:28 (line)
```
```rb
(rdbg) c # continue command
[23, 32] in ~/projects/rails-guide-example/app/controllers/posts_controller.rb
#1 ActionController::MimeResponds#respond_to(mimes=[]) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal/mime_responds.rb:205
# and 74 frames (use `bt' command for all frames)
Stop by #0 BP - Line /Users/st0012/projects/rails-guide-example/app/controllers/posts_controller.rb:28 (line)
=>#0 PostsController#create at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:25
#1 ActionController::BasicImplicitRender#send_action(method="create", 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
# and 72 frames (use `bt' command for all frames)
(rdbg) b @post.save # break command
#0 BP - Method @post.save at /Users/st0012/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/suppressor.rb:43
```
```rb
(rdbg) c # continue command
[39, 48] in ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/suppressor.rb
=> 44| SuppressorRegistry.suppressed[self.class.name] ? true : super
45| end
46|
47| def save!(**) # :nodoc:
48| SuppressorRegistry.suppressed[self.class.name] ? true : super
=>#0 ActiveRecord::Suppressor#save(#arg_rest=nil) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/suppressor.rb:44
Stop by #0 BP - Method @post.save at /Users/st0012/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/suppressor.rb:43
=>#0 PostsController#create at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:25
#1 ActionController::BasicImplicitRender#send_action(method="create", 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
=>#0 ActiveRecord::Validations#raise_validation_error at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/validations.rb:80
#1 ActiveRecord::Validations#save!(options={}) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/validations.rb:53
# and 88 frames (use `bt' command for all frames)
Stop by #1 BP - Catch "ActiveRecord::RecordInvalid"
=>#0 PostsController#create at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:25
#1 ActionController::BasicImplicitRender#send_action(method="create", 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
# and 72 frames (use `bt' command for all frames)
(rdbg) watch @_response_body # command
#0 BP - Watch #<PostsController:0x00007fce69ca5320> @_response_body =
```
```rb
(rdbg) c # continue command
[173, 182] in ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal.rb
173| body = [body] unless body.nil? || body.respond_to?(:each)
174| response.reset_body!
175| return unless body
176| response.body = body
177| super
=> 178| end
179|
180| # Tests if render or redirect has already happened.
181| def performed?
182| response_body || response.committed?
=>#0 ActionController::Metal#response_body=(body=["<html><body>You are being <ahref=\"ht...)at~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal.rb:178#=> ["<html><body>You are being <ahref=\"ht...
#1 ActionController::Redirecting#redirect_to(options=#<Postid:13,title:"qweqwe",content:...,response_options={:allow_other_host=>false}) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/actionpack-7.0.0.alpha2/lib/action_controller/metal/redirecting.rb:74
# and 82 frames (use `bt' command for all frames)
Stop by #0 BP - Watch #<PostsController:0x00007fce69ca5320>@_response_body = -> ["<html><body>You are being <ahref=\"http://localhost:3000/posts/13\">redirected</a>.</body></html>"]
In addition to different types of breakpoints, you can also specify options to achieve more advanced debugging workflows. Currently, the debugger supports 4 options:
Please also note that the first 3 options: `do:`, `pre:` and `if:` are also available for the debug statements we mentioned earlier. For example:
```rb
[2, 11] in ~/projects/rails-guide-example/app/controllers/posts_controller.rb
2| before_action :set_post, only: %i[ show edit update destroy ]
3|
4| # GET /posts or /posts.json
5| def index
6| @posts = Post.all
=> 7| debugger(do: "info")
8| end
9|
10| # GET /posts/1 or /posts/1.json
11| def show
=>#0 PostsController#index at ~/projects/rails-guide-example/app/controllers/posts_controller.rb:7
#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
=>#0 ActiveRecord::Validations#raise_validation_error at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/validations.rb:80
#1 ActiveRecord::Validations#save!(options={}) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/validations.rb:53
# and 88 frames (use `bt' command for all frames)
```
Once the catch breakpoint is triggered, it'll print the stack frames
```rb
Stop by #0 BP - Catch "ActiveRecord::RecordInvalid"
(rdbg:catch) bt 10
=>#0 ActiveRecord::Validations#raise_validation_error at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/validations.rb:80
#1 ActiveRecord::Validations#save!(options={}) at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/validations.rb:53
#2 block in save! at ~/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-7.0.0.alpha2/lib/active_record/transactions.rb:302
```
This technique can save you from repeated manual input and make the debugging experience smoother.
Web Console is a bit like `debug`, but it runs in the browser. You can request a console in the context of a view or a controller on any page. The console would be rendered next to your HTML content.
There is an excellent article about detecting and fixing memory leaks at Derailed, [which you can read here](https://github.com/schneems/derailed_benchmarks#is-my-app-leaking-memory).