Use bundle exec rake or just rake?

2019-01-10 06:12发布

问题:

I learned Rails using just the rake command like rake db:migrate; however, I read that I should be using the bundle exec rake ... instead of just plain rake. Now I'm confused about which to use.

Should I be using bundle exec rake instead of just plain rake or is it just a preference thing? Any insight would be much appreciated! Thanks!

回答1:

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.



回答2:

$ 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.



回答3:

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.