How to Debug Rails Source Code
Reading the Rails source code is a great way to understand how a feature works in Rails. However, stepping through the specific Rails method you're interested in is even better. You can inspect the local variables, follow the conditional path, and learn exactly what's happening behind the scenes. This post shows how you can debug the Rails source code to do exactly that.
Yesterday, as I was researching the authenticity tokens in Rails, I wanted to learn how Rails verifies the authenticity tokens. So I read the method description and the source code in the Rails API.
At first glance, the method looks straightforward. Upon receiving a request, Rails checks if the request is verified and calls the handle_unverified_request
method if it's not verified.
# actionpack/lib/action_controller/metal/request_forgery_protection.rb
def verify_authenticity_token # :doc:
mark_for_same_origin_verification!
if !verified_request?
logger.warn unverified_request_warning_message if logger && log_warning_on_csrf_failure
handle_unverified_request
end
end
Reading the source code of the verified_request?
method reveals that a few different checks need to happen to verify a request. Since Ruby is so readable, you can still read the following code and understand what's going on, but it would be sweet to step inside each method and understand precisely how Rails verifies a request.
def verified_request? # :doc:
!protect_against_forgery? || request.get? || request.head? ||
(valid_request_origin? && any_authenticity_token_valid?)
end
Debugging Rails Source Code
Let's say I want to debug the verified_request?
method. For this, I need to open the source file where that method is defined and insert a breakpoint in it.
Step 1: Open the source file
To open the relevant gem, go to your application in the terminal and run the bundle open gem_name
command. Since the above method is defined in the RequestForgeryProtection
module defined in the ActionPack gem, I will open that.
> bundle open actionpack
Assuming you have configured the EDITOR
environment variable, Ruby will open the above gem in the editor so you can inspect the code. Now you can navigate to the file containing the code you're interested in.
Step 2: Insert a breakpoint
For debugging the method, we need to insert a breakpoint. For this, I will use the pry-byebug
gem. If you aren't already using it, you can install it using the bundle add pry-byebug
command. Also, define the following debugger shortcuts in the ~/.pryrc
file.
if defined?(PryByebug)
Pry.commands.alias_command 'c', 'continue'
Pry.commands.alias_command 's', 'step'
Pry.commands.alias_command 'n', 'next'
Pry.commands.alias_command 'f', 'finish'
end
Once set up, put a breakpoint using the binding.pry
statement at the beginning of the method.
def verified_request?
binding.pry
!protect_against_forgery? || request.get? || request.head? ||
(valid_request_origin? && any_authenticity_token_valid?)
end
That's it. Save the file.
Step 3: Restart the application
If your application is running, restart it, so Rails loads the latest source code containing our breakpoints. Now, Ruby will pause the execution wherever you have placed the breakpoint when your application is running.
Now you can step through the Rails source code as you'd in your regular application.
I hope it helps. If you have any questions or run into any problems, let me know. I look forward to your feedback.