Why do I get NameError with `bundle exec ruby [file]` given that the necessary gem is in Gemfile?

Question

I'm doing some messing around to try to understand better how bundler works. I have just three files in my working directory:

Gemfile Gemfile.lock test.rb

All the Gemfile has is gem "slop" and test.rb looks like this:

puts Slop.parse

When I run bundle exec test.rb I get a NameError due to not having a require statement:

[ec2-user@xx my_app]$ bundle exec ruby test.rb
test.rb:1:in `<main>': uninitialized constant Slop (NameError)

But if I run bundle console, Bundler loads the gem correctly and I can run Slop.parse from the console without having to explicitly type require "slop":

[ec2-user@xx my_app]$ bundle console
irb(main):001:0> Slop.parse
=> #<Slop::Result:0x00000001339838...

So what am I missing? I was under the impression that since I don't have require: false in my Gemfile, Slop should be loaded when I run bundle exec ruby test.rb and I shouldn't need to put the require "slop" line in the file.


Show source
| ruby   | rubygems   | bundler   | gemfile   2016-07-04 20:07 3 Answers

Answers to Why do I get NameError with `bundle exec ruby [file]` given that the necessary gem is in Gemfile? ( 3 )

  1. 2016-07-04 21:07

    You need to config bundler to require all gems on your Gemfile like this:

    require 'rubygems'
    require 'bundler/setup'
    Bundler.require(:default)
    

    Check the docs at http://bundler.io/v1.12/bundler_setup.html

  2. 2016-07-04 22:07

    I was under the impression that since I don't have require: false in my Gemfile, Slop should be loaded when I run bundle exec ruby test.rb and I shouldn't need to put the require "slop" line in the file.

    The bundler docs say:

    Specify your dependencies in a Gemfile in your project's root:

    source 'https://rubygems.org'
    
    gem 'nokogiri'   #<======HERE
    

    Inside your app, load up the bundled environment:

    require 'rubygems' 
    require 'bundler/setup'
    
    # require your gems as usual 
    require 'nokogiri'   #<========AND HERE
    

    As for this:

    I was under the impression that since I don't have require: false in my Gemfile, Slop should be loaded when I run bundle exec ruby test.rb and I shouldn't need to put the require "slop" line in the file.

    The bundler docs are horrible on this point. As far as I can tell, :require => false is a Rails specific thing, which is used to decrease load times on project startup. In a rails app, specifying require: false means that the gem won't be loaded until you manually require the gem. If you don't specify :require => false, then the gem will be loaded automatically--however that is because rails code is written to do that automatic loading. Your app has no code that performs a similar function.

    Edit: Made a mistake while testing. So here's the way it works: In a non rails app, e.g. in your test.rb, if you want to automatically require all the gems specified in your Gemfile, you need to write:

    Bundler.require :default
    

    The Bundler docs mention that in the fine print here:

    Specify :require => false to prevent bundler from requiring the gem, but still install it and maintain dependencies.

    gem 'rspec', :require => false
    gem 'sqlite3'
    

    In order to require gems in your Gemfile, you will need to call Bundler.require in your application.

    I'm not sure why that requirement was only mentioned in conjunction with require: false instead of being stated at the outset.

    And, in your Gemfile if you specify:

    gem 'slop', :require => false
    

    (as well as Bundler.require :default in test.rb), then you also have to explicitly require the slop gem in test.rb:

     require 'slop'  
    

    In other words, Bundler.require :default automatically requires all the gems in your Gemfile except the gems marked with require: false. For gems marked with require: false, you have to manually write require 'gem_name' in your app.

    Therefore, neydroid posted the correct solution.


    * In your Gemfile, you can nest gems in groups, which affects how Bundler.require() works. See the Bundler docs on groups.

  3. 2016-07-04 23:07

    You should add the require "slop" inside your test.rb

Leave a reply to - Why do I get NameError with `bundle exec ruby [file]` given that the necessary gem is in Gemfile?

◀ Go back