Why do we bundle exec?

A common question I get is why do we need to prepend a command with bundle exec? Running the command by itself seems to work most of the time so what is difference? We know that rake db:migrate (for example) is the command we want to run. We know that bundle install is how you install all of the contents of a Gemfile which should install all the correct versions from the Gemfile.lock. If you have that in git so surely it can’t be different versions of the gem (it can be)? The question is why are we stringing these commands together and do we need to do it even if we don’t get an error?

When you run rake db:migrate you are running commands on gems. Specifically you are running the commands on the versions of gems that are installed on your operating system now. For example, if you ran:

$ rails new project-name

then the files you generate will be very different depending on if you have rails 6 or rails 3 installed. Different (unexpected) files is a recipe for bugs.

So how about bundle exec rake db:migrate (or any other command with the bundle exec in front of it)? Bundle exec is a command in bundler that forces the running of the command while in the context of the related bundle. So this means if rails 6 is the newest but you are using rails 5 then the command will happen in the context of rails 5. Correct dependencies means less weird bugs of unknown origin.

This buginess happens a lot when your Gemfile.lock has different gem versions installed than the versions of the gems installed on your computer. You know this has happened if you get a warning after running rake or rspec that looks like:

You have already activated i18n 1.8.5, but your Gemfile requires i18n 0.9.5. 
Prepending "bundle exec" to your command may solve this.

A common solution is to set be as an alias for bundle exec. You can check if you have already set it up (or if you are using be for something else) like this:

$ alias be

If you don’t get any text returned back then the bash alias is empty and you can use it for bundle exec (it should be empty or possibly already have bundle exec in it). You can change your .bash_profile file by running this command to open it:

sudo vim ~/.bash_profile

It should require your password but will let you edit the file if it exists.

Then you press i to go into insert mode and add:

# .bash_profile or .zshrc
alias be='bundle exec'

Then you press esc to go back into command mode, then :w and enter to write, and then :q and enter to quit the file. Once you reload your terminal (quit it and start it again) then you can run:

$ alias be

That should return be='bundle exec' which means you are good to go.

Now prepending a command with be should work fine. Example:

$ be rake db:migrate

This is a common solution instead of endlessly typing bundle exec.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *