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 different? 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 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.
after running rake or rspec.
A common solution for lazy programmers 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 get nothing back then it is empty and you can use it. Just add:
# .bash_profile or .zshrc alias be=‘bundle exec’
to your .bash_profile and then you are good to go about running:
$ be rake db:migrate
instead of endlessly typing bundle exec.