1
votes

I'm trying to do the "hello rspec" example from "The RSpec Book" and rspec complains it can't find "rails_helper". It doesn't complain in directories containg rails apps with rspec installed in the app-specific gemset. Rails is not installed in either of the gemsets in the rvm GEM_PATH for hello.

I set up the hello directory with: rspec --init.

I'm puzzled because this is not a Ruby On Rails project. I can't figure out where rspec is being told to require rails_helper. I'd appreciate any suggestions. Thanks!

**Leigh

  Mingus:hello $ rspec
    /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- rails_helper (LoadError)
        from /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration.rb:1283:in `block in requires='
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration.rb:1283:in `each'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration.rb:1283:in `requires='
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration_options.rb:109:in `block in process_options_into'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration_options.rb:108:in `each'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration_options.rb:108:in `process_options_into'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration_options.rb:21:in `configure'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/runner.rb:101:in `setup'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/runner.rb:88:in `run'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/runner.rb:73:in `run'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/runner.rb:41:in `invoke'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/exe/rspec:4:in `<top (required)>'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/bin/rspec:23:in `load'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/bin/rspec:23:in `<main>'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/bin/ruby_executable_hooks:15:in `eval'
        from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/bin/ruby_executable_hooks:15:in `<main>'

Here are the path vars from /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib/rspec/core/configuration.rb:1283:in `block in requires='

  # @private
  def requires=(paths)
    directories = ['lib', default_path].select { |p| File.directory? p }
    RSpec::Core::RubyProject.add_to_load_path(*directories)
    STDERR.puts "paths  ------>>   #{paths}"
    STDERR.puts "default_path  ------>>   #{default_path}"
    STDERR.puts "$LOAD_PATH  ------>>   #{$LOAD_PATH}"
    paths.each { |path| require path }
    @requires += paths
  end

  paths  ------>>   ["spec_helper", "rails_helper", "spec_helper"]
  default_path  ------>>   spec
  $LOAD_PATH:
  /Users/leigh/Programming/wapp_dev/hello/spec
  /Users/leigh/.rvm/gems/ruby-2.2.1@global/gems/executable-hooks-1.3.2/lib
  /Users/leigh/.rvm/gems/ruby-2.2.1@global/extensions/x86_64-darwin-14/2.2.0-static/executable-hooks-1.3.2
  /Users/leigh/.rvm/gems/ruby-2.2.1@global/gems/bundler-unload-1.0.2/lib
  /Users/leigh/.rvm/gems/ruby-2.2.1@global/gems/rubygems-bundler-1.4.4/lib
  /Users/leigh/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.10.3/lib
  /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-support-3.3.0/lib
  /Users/leigh/.rvm/gems/ruby-2.2.1@rspec-hello/gems/rspec-core-3.3.1/lib
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/x86_64-darwin14
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/vendor_ruby/2.2.0
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/vendor_ruby/2.2.0/x86_64-darwin14
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/vendor_ruby
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0
  /Users/leigh/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/x86_64-darwin14
~/.rspec:
    --color
    --format documentation
    --require spec_helper
    #--require rails_helper
hello/.rspec:
    --color
    --require spec_helper
hello/greeter_spec.rb:
  describe "RSpec Greeter" do
    it "should say 'Hello RSpec!' when it receives the greet() message" do
      greeter = RSpecGreeter.new
      greeting = greeter.greet
      greeting.should == "Hello RSpec!"
    end
  end
2
Must be somewhere in your environment. Start picking through your dot files and ENV vars looking for the culprit.Philip Hallstrom

2 Answers

1
votes

RSpec has several locations it aggregates the options from (listed in lowest to highest precedence):

  • ~/.rspec
  • .rspec
  • .rspec-local
  • command line switches
  • SPEC_OPTS environment variable

I would double check all of those. It may seem silly but be sure your ~/.rspec file has been saved; done this one to myself too many times. Also, stop any pre-loaders such as spring, guard, and spork. I would also check to make sure you didn't accidentally alias rspec with something else (i.e. check which rspec and alias | grep rspec).

If all that fails, you can peek into RSpec's internals (this is specific to your current version, but may work for others). Add the following to a file in your project for example: trace_opts.rb

require 'rspec/core'
module TraceOpts
  def self.trace_options(opt)
    name = opt.to_s.split('_').map(&:capitalize).join(' ')
    define_method(opt) do |*args, &block|
      super(*args, &block) { |opts| puts "#{name}: #{opts}" }
    end
  end

  def self.trace_file(opt)
    name = opt.to_s.split('_').map(&:capitalize).join(' ')
    define_method(opt) do |*args, &block|
      super(*args, &block).tap { |opts|
        opts = opts ? File.expand_path(opts) : "No File Specified"
        puts "#{name}: #{opts}"
      }
    end
  end

  trace_options :env_options
  trace_options :command_line_options
  trace_options :custom_options
  trace_options :local_options
  trace_options :project_options
  trace_options :global_options

  trace_file :custom_options_file
  trace_file :project_options_file
  trace_file :local_options_file
  trace_file :global_options_file
end
RSpec::Core::ConfigurationOptions.prepend(TraceOpts)
RSpec::Core::Runner.invoke

Then run it with ruby trace_opts.rb and it should show you where things are being loaded from.

EDIT: The option files that RSpec reads are parsed as ERB files. They are then fed through OptionParser. Setting can be ignored at the ERB parsing level by using the ERB comment:

<%# --require rails_helper %>

When the line is commented out with plain Ruby # it is provided to the option parser. Depending where in the order this occurs can have an affect on what the option parser does. In the few permutations I tried the commented option was included as part of the files_or_directories_to_run. The RSpec configuration code removes that particular option before proceeding.

0
votes

I now know that the # mark is NOT a comment indicator in the .rspec file!

It showed that ~/.rspec was including rails_helper when I thought the # made it invisible. Removing "#--require rails_helper" did the trick!

Thanks for the script, Aaron, and for taking the time to help out!

**Leigh