Debugging Rails Applications with RubyMine's Graphical Debugger
A practical guide to configuring RubyMine's graphical debugger for Rails: SDK setup, debug backend gems, run configurations, breakpoints, stepping, variable inspection, and recovery from common startup failures.
29 Jul 2025, 17:58 UTC

Desired Outcome
Attach RubyMine's debugger to a running Rails server, pause execution at breakpoints, inspect variables and call stacks, and evaluate expressions interactively — all without leaving the IDE.
Prerequisites
Project SDK and Debug Backend
RubyMine's debugger requires a compatible debug backend gem installed in the project's Ruby environment. For Ruby 3.x the IDE uses the debug gem (debug.rb); older Rubies historically relied on ruby-debug-ide plus debase. The IDE detects the Ruby version and prompts to install the correct backend when you first start a debug session.
Verify the SDK in Settings → Ruby SDK and Gems. Ensure the project SDK points to the interpreter you use for development (rbenv, RVM, asdf, or a Docker-based remote SDK). The debug backend must be available in the :development Gemfile group — if it's only in :test the IDE cannot load it.
Disable Spring for Debug Runs
Spring preloads application code and can cause breakpoints to be missed because the code running under the debugger isn't the same process the IDE attached to. The simplest workaround is to disable Spring for the debug configuration (see below) or run spring stop before starting the debugger.
Configure a Rails Run/Debug Configuration
- Open Run → Edit Configurations.
- Click + and choose Rails (or Ruby for a plain script).
- Name the configuration (e.g., "Rails Debug").
- Set Ruby SDK to the project SDK confirmed above.
- In Server, select Puma (or WEBrick) and ensure Start in debug mode is checked.
- Under Environment variables, add
DISABLE_SPRING=1to prevent Spring interference. - Optional: set a custom Port if 3000 is occupied.
- Click OK.
Set Breakpoints
Open any Ruby file (controller, model, service, view). Click the gutter next to a line number — a red dot appears. Right-click the breakpoint to add conditions, log expressions, or convert it to an exception breakpoint.
Example: In app/controllers/posts_controller.rb, set a breakpoint on the line @post = Post.find(params[:id]) inside the show action. Add a condition params[:id] == "42" to pause only for that record.
Start the Debug Session
Select the configuration in the toolbar and click the Debug icon (bug) — not the green Run triangle. RubyMine launches the Rails server with the debug backend attached. The Debug tool window opens showing Frames, Threads, Variables, and Watches panes.
Step Through Code
When a breakpoint hits, execution suspends. Use the stepping toolbar:
- Step Over (F8) — execute the current line, stay in the same frame.
- Step Into (F7) — dive into the method call on the current line.
- Step Out (Shift+F8) — finish the current method and return to the caller.
- Resume (F9) — continue until the next breakpoint.
The Frames pane shows the call stack; click any frame to inspect its local variables.
Inspect Variables and Evaluate Expressions
The Variables pane lists locals and instance variables for the selected frame. Expand objects to see their attributes. Add custom watches by clicking + in the Watches pane (e.g., @post.comments.count).
For ad-hoc evaluation, press Alt+F8 (or Option+F8 on macOS) to open the Evaluate Expression dialog. Enter any Ruby expression — method calls, arithmetic, block iteration — and click Evaluate. The result appears inline.
Concrete example: While paused in the show action, open Evaluate Expression and run Post.where(published: true).count. The returned integer confirms the scope works as expected without modifying code.
Log-Only and Exception Breakpoints
Right-click a breakpoint → More → check Log evaluated expression and uncheck Suspend. The expression result prints to the Debug console without pausing — useful for tracing values in hot paths.
Add exception breakpoints via Run → View Breakpoints → + → Ruby Exception Breakpoint. Enter ActiveRecord::RecordNotFound to pause whenever that exception is raised, even if rescued.
Common Debugger Startup Failures and Recovery
Backend Gem Missing or Version Mismatch
If the Debug console shows LoadError: cannot load such file -- debug or similar, the backend gem isn't installed for the current SDK. RubyMine usually prompts "Install missing gems?" — accept it. If the prompt doesn't appear, open the Gemfile, ensure gem 'debug', group: :development is present, run bundle install in the terminal, then restart the debug configuration.
Breakpoints Not Hit
- Confirm Spring is disabled (
DISABLE_SPRING=1in the configuration orspring stop). - Verify the breakpoint line contains executable code (not a comment or empty line).
- Check that the server process shown in the Debug tool window matches the endpoint you're hitting (port, PID).
Debugger Attaches but Immediately Detaches
This often means the debug backend crashed on startup. Open File → Invalidate Caches → Invalidate and Restart. After restart, reinstall the backend gem via the IDE prompt. Also verify the Gemfile doesn't exclude the debug gem with platforms or group restrictions that prevent it from loading in the current environment.
Remote or Docker-Based SDKs
For Docker Compose setups, use a Remote SDK configured via Settings → Ruby SDK and Gems → + → New Remote. Map the project directory to the container path. The debug configuration must point at this remote SDK. Port forwarding for the debug port (default 12345) must be declared in docker-compose.yml.
Verification Checklist
- Start the "Rails Debug" configuration.
- Visit
http://localhost:3000/posts/42(or the route matching your conditional breakpoint). - Execution pauses at the breakpoint; the Debug tool window shows the
showframe. - Variables pane displays
@post,params, and local variables. - Press Alt+F8, evaluate
@post.title.upcase— result matches the database value. - Press F9 to resume; page renders normally in the browser.
Limitations
- Background jobs (Sidekiq, Resque, GoodJob) run in separate processes — they require their own debug configurations attached to the job worker, not the web server.
- Debug overhead is significant: expect 2–10× slower request latency with active breakpoints.
- Hot code reloading (Zeitwerk autoloading) works, but structural changes (new classes, renamed methods) may require a debugger restart to refresh the backend's type information.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.