Debugging in RubyMine
To learn more about debugging capabilities available in RubyMine, refer to the help topics and tutorials from the Debug section.
One of the main advantages of IDEs over text editors is the debugging experience. In this blog post, we’ll review the rich debugging capabilities available in RubyMine and then we’ll have a quick rundown of the new debugging features added in v2019.2. These include performance optimizations, Smart Step Into, block breakpoints, and others.
The RubyMine debugger provides various ways to examine the state of a running application: you can step through your code and check variable values, set watches on variables to see when values change, and so on. All of these features are applied to Ruby projects and Rails applications. You can debug everything from .rb scripts to .erb and .haml views.
Let’s dig a little deeper into the debugging process and see how we can start a debugging session, set and configure breakpoints, evaluate variables and expressions, and all the other little useful things you should know about in between.
- Start debugging
- Stepping through a program
- Examine variables
- Configure breakpoints
- Debugging Rails apps
- Smart step into, block breakpoints and more
Start debugging
First, let’s create a new Ruby project from scratch. This will be a script for solving a quadratic equation without additional checks (for example, whether or not the discriminant is equal to or less than 0):
a = 1 b = -3 c = 2 def solve(a, b, c, sign) discriminant = b ** 2 - 4 * a * c (-b + (sign) * Math.sqrt(discriminant)) / (2 * a) end x1 = solve(a, b, c, 1) x2 = solve(a, b, c, -1) puts "x1 = #{x1}, x2 = #{x2}"
In this script, the x1 and x2 equation roots are determined by calling the solve method. This method accepts equation coefficients and a sign so you can determine both roots.
Before starting a debugging session, let’s set a breakpoint next to the following line:
x1 = solve(a, b, c, 1)
To do this, click the left gutter next to this line. Alternatively, you can place the caret on this line and press Ctrl+F8 / ⌘F8. The script will be suspended at this line and we can check the program’s state.
To start a debugging session, do the following:
- Press Ctrl twice and type the following command in the invoked popup:
ruby script.rb
- Press and hold down the Shift key (the dialog title will be changed to Debug) and press Enter.
If your project SDK doesn’t have debugging gems installed, RubyMine will suggest that you install them:
That’s it! We are ready to start debugging.
Stepping through a program
After starting the debugging session, RubyMine stops execution on the 10th line.
The editor displays the current variable values on the right. Note that x1 is not evaluated because the solve method is not called yet. Let’s see what capabilities RubyMine provides to step through program execution further.
Step over will proceed to take us to the next line in the current scope (for example, it will take us to the next line), without going into any method calls on the way. To step over, click the button in the debugger’s toolbar or press F8. In our case, the IDE then steps over the solve method and goes to the 11th line – to the calculation of the second root. Clicking F8 another time takes us to the puts method call (and skips going into the solve method).
Another way of stepping through the code is to use step into which causes the debugger to go into the method calls or blocks on the current line and follow them through. If there are multiple method calls or blocks, you can choose the desired target by using the new smart step into functionality. Go to Smart step into, block breakpoints and more to learn more.
To step into the method, click the button on the toolbar or press F7. In our example, the debugger steps into the solve method and stops at the first method line. Press F7 several times to walk through each line of the solve method until you return back to the second method call (line 11).
One more useful stepping feature is Run to cursor. It allows you to stop the code executing at the caret position without adding another breakpoint. To do this, click the Run to cursor button or press Alt+F9 / ⌥F9 at the required caret position. The debugger will jump right to this line.
If you no longer want to debug a method (e.g., the one you’ve just stepped into), you can simply step out (Shift+F8) of it. The debugger will execute the remaining lines of the method and set the execution pointer at the statement following the method call.
Finally, you can resume program execution by clicking the button (F9 / ⌥⌘R). In this case, the script will be executed until the next breakpoint is hit.
Examine variables
When a program reaches a breakpoint and stops, you can investigate the state of the application and the values of variables in different places. Let’s look at the main UI elements used to do this:
1 – The Frames pane displays the call stack from the first call (bottom frame) to the last one (top frame), where a program was suspended. In the example above, the stack consists of two calls:
- script.rb:10 – the 10th line where the solve method is called
- solve [script.rb:7] – the 7th line which is within the solve method definition
You can switch between these frames and examine the program’s state at different stages.
2 – The RubyMine editor allows you to examine the variable values for the currently selected frame right in the editor.
Hint: You can disable it from showing variables inline by using the Show values inline option from the Build, Execution, Deployment | Debugger | Data Views page in the Settings/Preferences (Ctrl+Alt+S / ⌘,) dialog.
3 – The Variables pane allows you to examine variable values evaluated for the current frame. Here you can add new variables or expressions to watch their values during program execution.
Evaluate Expressions
One other way to evaluate expressions is to use the Evaluate dialog. You can invoke it using the button.
The debugger also has a Console tab that enables you to interact with a debugged application with an IRB-like console.
Configure breakpoints
Earlier in this post, we showed how to suspend a program and examine its state at specific lines using breakpoints. Now let’s consider some advanced capabilities related to breakpoints. For each breakpoint, you can configure a set of settings. To do this, right-click the breakpoint and click More in the invoked popup.
Alternatively, press Ctrl+Shift+F8 / ⇧⌘F8. In the Breakpoints dialog, select the required breakpoint in the Ruby Line Breakpoints group and specify the required settings. For example, you can set a condition for hitting a breakpoint. A condition is a Ruby boolean expression evaluating to either true or false.
Disabling the Suspend option can be useful if you need to obtain logging information or calculate an expression at a certain point without interrupting the program. In such cases, you might find the Evaluate and log option useful; it enables you to evaluate expressions when a breakpoint is hit.
The result will be displayed in the debugger console output later.
Exception breakpoints
In the section above, we considered line breakpoints that can be set on executable lines of code. There is another kind of breakpoint – an exception breakpoint – that is triggered when a specified exception is thrown. These types of breakpoints apply globally to the exception condition and do not require a particular source code reference.
Let’s create a breakpoint that will be triggered when the Math::DomainError is raised. Press Ctrl+Shift+F8 / ⇧⌘F8 or select Run | View Breakpoints from the main menu. In the invoked dialog, press Ctrl+N / ⌘N or click the Add button, and select Ruby Exception Breakpoint. Find the DomainError class in the Math module, click OK and then click Done.
Then, if we change the equation coefficients to make the discriminant negative, RubyMine will stop executing the code at the corresponding script line to allow you to examine what’s wrong with the program.
Debugging Rails apps
Debugging Rails applications in RubyMine is as easy as debugging scripts – you can set breakpoints and run the Rails server in debug mode.
To learn more about debugging a sample Rails application, check out this Getting started guide.
Below are several useful features related to debugging Rails applications in RubyMine:
- RubyMine allows you to debug Rails applications with Spring. This may require updating a system or project Spring configuration file to load the debugger into every process forked by Spring. When you start debugging, RubyMine will show you a dialog with the following choices.
- You can debug views by setting breakpoints within the ERB and HAML files.
- When stepping through a program, RubyMine allows you to explore gem sources.
You can disable this capability and step only through the project sources using the Ignore non-project sources option, which can be found at Setting/Preferences | Build, Execution, Deployment | Debugger | Stepping.
You can patch the system or project config file to enable debugging with Spring.
Smart step into, block breakpoints, and more
While debugging Ruby code, you may reach several methods or blocks. Starting with this EAP, you can choose the desired method or block using the new Smart Step Into functionality. Let’s see this feature in action using the Sample Rails app – a blogging application that allows users to create blog posts and follow other users.
When we click Follow in the browser, our Rails application invokes the create action from the RelationshipController (app/controllers/relationships_controller.rb). If we set a breakpoint at the first line within the create method, RubyMine suspends the program’s execution at this line. In the animation below, we can see how we could step through the method using the new Smart Step Into and select the desired methods or blocks.
Along with new stepping, you can set breakpoints at not only lines but at blocks, too. Click the left gutter icon and select the block where you want to set a breakpoint. In the animation below, the program is suspended at the block where the breakpoint was set.
If you select All, this breakpoint will be hit twice when you resume (F9 / ⌥⌘R) the program.
These are not the only improvements in our debugger. We have also significantly improved the performance and various features related to stepping and examining a program’s state. Check out new capabilities in RubyMine, and let us know about any issues in the comments section. You can also submit issues or feature suggestions to YouTrack. Thank you!
Cheers,
Your RubyMine Team