使用捆绑执行耙或只是耙?

我只使用 rake 命令学习了 Rails,比如 rake db:migrate; 但是,我读到我应该使用 bundle exec rake ...而不是仅仅使用简单的 rake。现在我不知道该用哪个了。

我应该使用 bundle exec rake而不是仅仅使用简单的 rake,还是仅仅是一种偏好?有任何见解,我将不胜感激!谢谢!

18432 次浏览

bundle exec executes a command in the context of your bundle.

That means it uses the gems specified in your Gemfile. Much of the time, running bundle exec rake foo has the same results as if you just ran rake foo, especially if you have the same gems installed systemwide as in your Gemfile. However, some applications may specify different versions of gems than the ones you have installed systemwide, and may want those exact gems and versions to be able to run correctly. If you just run without bundle exec, you may get some weird errors.

Using bundle exec guarantees that the program is run with the environment specified in the gemfile, which hopefully means it is the environment that the creators of the program want it to be run in, which hopefully means it should run correctly no matter what weird setup you have on your computer.

It basically standardizes the environment under which the program is run. This helps avoid version hell and makes life much easier.

See http://bundler.io/v1.3/man/bundle-exec.1.html for more info.

running any exacutable without bundle exec will have Rubygems fetching the latest version of the gem installed in your system.

By adding the bundle exec prefix instead will have the executable running in the context of your Gemfile.lock, which means that will be run using the version defined in the gem file.

$ bundle exec rake db:migrate
Uses the version of rake specified in the Gemfile to execute the rake task db:migrate.

But there is no rake gem specified in the Gemfile!
Yes, but a rake gem was installed as a dependency of some other gem--look in Gemfile.lock. So the rule must be: Uses the version of rake specified in Gemfile.lock.

But Gemfile.lock doesn't specify a specific version--it specifies a version greater than x.y!
Then the rule must be: Uses the version of rake that was installed in the current gemset.

$ rake db:migrate
Normally, when you issue a command on the command line, e.g. rake, your system searches for the command in the list of directories specified in your PATH environment variable. The first directory that contains the command is the version of the command that is used. To see which directory that is, you can do:

$ which rake

So if you execute,

$ rake db:migrate

that may use a different rake gem than the one you installed with bundle install. But, even if your system finds the same rake version as bundle exec, any gems required by the rake source code will be searched for in places outside your project's gemset. Therefore, there are many ways that just:

$ rake db:migrate

can screw things up.

According to the Ruby on Rails Tutorial Book(free online), section 3.6, if you are using rvm 1.11.x+ then you do not need to preface commands with bundle exec.