394

What does bundle exec rake db:migrate mean? Or just bundle exec rake <command> in general?

I understand that bundle takes care of maintaining things in the Gemfile. I know what the word "exec" means. I understand that rake maintains all the different scripty things you can do, and I know that db:migrate is one of those. I just don't know what all these words are doing together. Why should bundle be used to execute rake to execute a database migrate?

0

7 Answers 7

507

bundle exec is a Bundler command to execute a script in the context of the current bundle (the one from your directory's Gemfile). rake db:migrate is the script where db is the namespace and migrate is the task name defined.

So bundle exec rake db:migrate executes the rake script with the command db:migrate in the context of the current bundle.

As to the "why?" I'll quote from the bundler page:

In some cases, running executables without bundle exec may work, if the executable happens to be installed in your system and does not pull in any gems that conflict with your bundle.

However, this is unreliable and is the source of considerable pain. Even if it looks like it works, it may not work in the future or on another machine.

10
  • 8
    Does that mean we should always run bundle exec, I have used ruby version manager to install ruby and ruby on rails. Commented Jan 3, 2012 at 10:30
  • 14
    @Edmund A "bundle" is an english word, meaning a group of similar things, usually tied up neatly. Specifically in this question, it refers to a group of Gems (self-contained ruby code libraries.) Bundler is the name of the software which we are using here to manage Gems. And bundle is the command which is used by Bundler.
    – ghoppe
    Commented Mar 30, 2013 at 4:33
  • 2
    I have impression that whenever we cd to a folder with Gemfile, the shell will automatically use the versions specified in Gemfile (e.g. Ruby version). Based on that assumption, I thought rake db:migrate would always run fine without bundle exec. CMIIW Commented Sep 12, 2014 at 9:10
  • 1
    @PahleviFikriAuliya that is only true if you have a .ruby-gemset file in your project root. There is also a .ruby-version file that sets your ruby version if using RVM.
    – Catfish
    Commented Nov 10, 2015 at 22:02
  • 1
    they could have just called it "local" or "global" to be more self-explanatory... kind of how npm has a regular install and a -g install. And they could have also chosen the shorter version to be the one that is used more frequently (the local one) instead.
    – ahnbizcad
    Commented Dec 22, 2015 at 9:40
186

You're running bundle exec on a program. The program's creators wrote it when certain versions of gems were available. The program Gemfile specifies the versions of the gems the creators decided to use. That is, the script was made to run correctly against these gem versions.

Your system-wide Gemfile may differ from this Gemfile. You may have newer or older gems with which this script doesn't play nice. This difference in versions can give you weird errors.

bundle exec helps you avoid these errors. It executes the script using the gems specified in the script's Gemfile rather than the systemwide Gemfile. It executes the certain gem versions with the magic of shell aliases.

See more on the man page.

Here's an example Gemfile:

source 'http://rubygems.org'

gem 'rails', '2.8.3'

Here, bundle exec would execute the script using rails version 2.8.3 and not some other version you may have installed system-wide.

5
  • 15
    I like this answer better than the chosen by the OP :D! Much more clearer. Commented Dec 17, 2013 at 15:38
  • 1
    So to add to this example: if the person simply ran rake db:migrate leaving out bundle exec then it would execute using a systemwide Gemfile where one may have rack at 1.5.2 (latest)?
    – Smokin Joe
    Commented Feb 19, 2014 at 20:26
  • much better answer, with concrete examples.
    – ahnbizcad
    Commented Feb 8, 2015 at 12:12
  • 2
    So bundle exec uses the "app-specific", local gems in your Gemfile of your app, and bundle uses the "machine-specific", global gems if you did gem install a_certain_gem. local vs global
    – ahnbizcad
    Commented Oct 12, 2015 at 2:25
  • Much better answer than the chosen one.
    – Boon
    Commented Oct 23, 2015 at 22:49
11

This comes up a lot when your gemfile.lock has different versions of the gems installed on your machine. You may get a warning after running rake (or rspec or others) such as:

You have already activated rake 10.3.1, but your Gemfile requires rake 10.1.0. Prepending "bundle exec" to your command may solve this.

Prepending bundle exec tells the bundler to execute this command regardless of the version differential. There isn't always an issue, however, you might run into problems.

Fortunately, there is a gem that solves this: rubygems-bundler.

$ gem install rubygems-bundler

$ $ gem regenerate_binstubs

Then try your rake, rspec, or whatever again.

1
  • Still a great solution in 2020.
    – Brateq
    Commented Apr 4, 2020 at 20:08
7

It should probably be mentioned, that there are ways to omit bundle exec (they are all stated in chapter 3.6.1 of Michael Hartls Ruby on Rails Tutorial book).

The simplest is to just use a sufficiently up-to-date version of RVM (>= 1.11.x).

If you're restricted to an earlier version of RVM, you can always use this method also mentioned by calasyr:

$ rvm get head && rvm reload
$ chmod +x $rvm_path/hooks/after_cd_bundler
$ bundle install --binstubs=./bundler_stubs

The bundler_stubs directory should then also be added to the .gitignore file.

A third option is to use the rubygems-bundler gem if you're not using RVM:

$ gem install rubygems-bundler
$ gem regenerate_binstubs
1

When you directly run the rake task or execute any binary file of a gem, there is no guarantee that the command will behave as expected. Because it might happen that you already have the same gem installed on your system which have a version say 1.0 but in your project you have higher version say 2.0. In this case you can not predict which one will be used.

To enforce the desired gem version you take the help of bundle exec command which would execute the binary in context of current bundle. That means when you use bundle exec, bundler checks the gem version configured for the current project and use that to perform the task.

I have also written a post about it which also shows how we can avoid using it using bin stubs.

1

I have not used bundle exec much, but am setting it up now.

I have had instances where the wrong rake was used and much time wasted tracking down the problem. This helps you avoid that.

Here's how to set up RVM so you can use bundle exec by default within a specific project directory:

https://thoughtbot.com/blog/use-bundlers-binstubs

0

It means use rake that bundler is aware of and is part of your Gemfile over any rake that bundler is not aware of and run the db:migrate task.

Not the answer you're looking for? Browse other questions tagged or ask your own question.