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.