The Life‑Changing Magic of Ruby and Rails

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.

Subscribe to Akshay's Blog

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe