Every once in a while, a little bit of collective thought during the “impediments” portion of the daily scrum yields some immediate results…

 

Overview

A portion of our development team uses RubyMine as the primary source code editor / IDE for Ruby development. Our team lead (the other guy) is more of a purist and boasts a status of VIM Power User never leaving the Terminal window. Recently, RubyMine’s debugging capabilities just stopped working on both of our active Rails projects. More specifically, every time we attempted to use RubyMine’s debugger to launch a single spec or cuke with breakpoints set, the entire test file failed. Even tests that should have passed failed to execute while everything worked perfectly from the command line. The stack trace revealed nothing more than a cryptic error like the one below. I shortened it a bit to include only the important items. Pay special attention to “RuntimeError: Debugger.start is not yet called.”

/Users/kbeckman/.rvm/rubies/ruby-1.9.2-p180/bin/ruby -e at_exit{sleep(1)};$stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) /Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug-ide-0.4.17.beta5/bin/rdebug-ide --port 49226 -- /Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/bin/rspec /Users/kbeckman/Sites/Project/spec/models/post_spec.rb --require teamcity/spec/runner/formatter/teamcity/formatter --format Spec::Runner::Formatter::TeamcityFormatter
Testing started at 10:20 PM ...
Fast Debugger (ruby-debug-ide 0.4.17.beta5, ruby-debug-base 0.11.28) listens on 127.0.0.1:49226
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug-base19-0.11.24/lib/ruby_debug.bundle: warning: already initialized constant VERSION

RuntimeError: Debugger.start is not called yet.
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug19-0.11.6/cli/ruby-debug/processor.rb:130:in `breakpoints'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug19-0.11.6/cli/ruby-debug/processor.rb:130:in `at_breakpoint'
(eval):5:in `block in at_breakpoint'
<internal:prelude>:10:in `synchronize'
(eval):3:in `at_breakpoint'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug-base19-0.11.24/lib/ruby-debug-base.rb:42:in `at_breakpoint'
/Users/kbeckman/Sites/Project/spec/models/post_spec.rb:6:in `block (2 levels) in <top (required)>'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/hooks.rb:29:in `instance_eval'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/hooks.rb:29:in `run_in'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/hooks.rb:64:in `run_all!'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/hooks.rb:112:in `run_hook!'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/example_group.rb:176:in `eval_before_alls'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/example_group.rb:230:in `run'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/command_line.rb:27:in `block (2 levels) in run'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/command_line.rb:27:in `map'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/command_line.rb:27:in `block in run'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/reporter.rb:12:in `report'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/command_line.rb:24:in `run'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/runner.rb:55:in `run_in_process'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/runner.rb:46:in `run'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/rspec-core-2.3.1/lib/rspec/core/runner.rb:10:in `block in autorun'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug-ide-0.4.17.beta5/lib/ruby-debug-ide.rb:112:in `debug_load'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug-ide-0.4.17.beta5/lib/ruby-debug-ide.rb:112:in `debug_program'
/Users/kbeckman/.rvm/gems/ruby-1.9.2-p180@Project/gems/ruby-debug-ide-0.4.17.beta5/bin/rdebug-ide:87:in `<top (required)>'
-e:1:in `load'
-e:1:in `<main>'

2 examples, 2 failures, 0 passed

Finished in 0.002311 seconds

Process finished with exit code 0

 

Investigation

Back to the “impediments” portion of the daily scrum… This issue was brought to everyone’s attention and we chatted about it for a couple of minutes. Since he wasn’t using RubyMine, our team lead was the only developer not having any issues with debugging. We soon discovered a few days ago he added a require statement for the ruby-debug gem in our RSpec spec_helper.rb file. Bingo!

 

Resolution

It turns out that RubyMine automatically adds its own reference to the ruby-debug gem during its debugging process. With the new reference in our spec_helper.rb file, all RubyMine users had a dual reference (RubyMine’s version and to our project version in the RVM gemset). The runtime was unable to determine which gem version to use for debugging. With the issue discovered, the solution is easy. Adding a conditional statement in spec_helper.rb to ignore the ruby-debug reference (for RubyMine users only) solves the problem.

 

Step 1 – Set a Mac Environment Variable Indicating RubyMine Usage

Here’s a link to a System Preferences plug-in allowing you edit system environment variables via a GUI dialog. Or you can follow the steps in this post to manually edit your environment variables file. For documentation’s sake, here’s what my .MacOSX/environment.plist file looks like.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>USE_RUBYMINE</key>
    <string>TRUE</string>
</dict>
</plist>

 

Step 2 – Update spec_helper.rb to Conditionally Add the ruby-debug Gem

require 'rubygems'
require 'spork'
require 'webmock/rspec'
unless ENV["USE_RUBYMINE"] == "TRUE"
  require 'ruby-debug'
end