bundle exec vs non bundle exec. 

This article is part of the series [Everyday code].

We use bundler to pack parts of the Instruction Steps Framework, especially the parts that should be easy to port to the rails world. We learned something about Bundler so I decide to share it with everybody.

TL; DR;

Question is – which of these two should you use:

# Call bundle exec before rake
$ bundle exec rake 

# Call just rake
$ rake

‘bundle exec rake’ will look at what is written in your .gemspec/Gemfile while rake will use whatever is in your env.

Gem.. but in a box
gem inabox with bundler

Bundle exec

For example we use geminabox, a great tool to keep an internal repo of plugins. In this way rails projects could include the Instruction Steps framework directly as a gem. This makes it very easy for rails projects to use the Instruction Steps.

To put a gem in the repo one must execute:

$ gem inabox

You could make this call in three different ways. The difference is subtle, but important.

Most of the time the env in which your shell is working will be almost the same as the env in which the gem is bundled. Except with the cases when it is not.

From the shell

# This will use the env of the shell. Whatever you have in the shell.
$ gem inabox

From a rake file

If you have this rake file

require 'rails/all'

task :inabox do 
  system("gem inabox")
end

then you could call rake in the following ways:

rake inabox

# This will call rake in the env defined by the shell in which you are executing
$ rake inabox

bundle exec rake inabox

# This will call rake in the env of the gem
$ bundle exec rake inabox

When using the second call bundle will look at the ‘.gemspec’/’Gemfile’ and what is in the gemspec. If non of the gems in the .gemspec adds the ‘inabox’ command to the env then the command is not found and an error occurs like:

ERROR:  While executing gem ... (Gem::CommandLineError)
    Unknown command inabox

If ‘gem inabox’ is called directly from the shell it works, but to call gem inabox from a rake job you must have ‘geminabox’ as development dependency of the gem. When calling ‘gem inabox’ from a shell we are not using the development env of the gem, we are using the env of the shell. But once we call ‘bundle exec rake inabox’ and it calls ‘gem inabox’, this second call is in the environment of the gem. So we should have a development_dependency to the ‘geminabox’ gem:

 spec.add_development_dependency 'geminabox'

Nice. Simple, nice, logical. One just has to know it.