提问



bundle exec rake db:migrate是什么意思?或者只是bundle exec rake <command>?


我知道bundle负责维护Gemfile中的内容。我知道exec这个词是什么意思。我理解rake保留了你可以做的所有不同的脚本事情,我知道db:migrate就是其中之一。我只是不知道所有这些词在一起做什么。为什么bundle被用来执行rake来执行数据库迁移?

最佳参考


bundle exec是一个Bundler命令,用于在当前包的上下文中执行脚本(来自目录Gemfile的脚本)。rake db:migrate是 db 的脚本。 namespace和 migrate 是定义的任务名称。[28] [29] [30]


所以bundle exec rake db:migrate在当前包的上下文中使用命令db:migrate执行rake脚本。


至于为什么?我将从捆绑页面引用:[31]



  在某些情况下,如果可执行文件恰好安装在您的系统中并且不会引入任何与您的软件包冲突的gem,则运行不带bundle exec的可执行文件可能会有效。

  
  然而,这是不可靠的,并且是相当痛苦的根源。即使它看起来有效,但它可能在将来或其他机器上不起作用。


其它参考1


你正在程序上运行bundle exec。程序的创建者在某些版本的宝石可用时编写了它。程序Gemfile指定创建者决定使用的gem的版本。也就是说,脚本可以针对这些gem版本正确运行。


您的系统范围的Gemfile可能与此Gemfile不同。你可能有更新或更旧的宝石,这个脚本不会很好玩。这种版本的差异会给你带来奇怪的错误。


Bundle exec可以帮助您避免这些错误。它使用脚本的Gemfile中指定的gems而不是系统范围的Gemfile来执行脚本。它使用shell别名的魔法执行某些gem版本。


请参见手册页。[32]


这是Gemfile的一个例子:


source 'http://rubygems.org'

gem 'rails', '2.8.3'


这里,bundle exec将使用rails版本2.8.3执行脚本,而不是您可能已在系统范围内安装的其他版本。

其它参考2


当你的gemfile.lock在你的机器上安装了不同版本的gem时,会出现这种情况。运行rake(或rspec或其他)后,您可能会收到警告,例如:


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.


前置bundle exec告诉捆绑器执行此命令而不管版本差异。并非总是存在问题,但是,您可能会遇到问题。


幸运的是,有一个宝石可以解决这个问题:rubygems-bundler。


$ gem install rubygems-bundler搜索结果
$ $ gem regenerate_binstubs


然后尝试你的耙子,rspec或其他任何东西。

其它参考3


应该提到的是,有一些方法可以省略bundle exec(它们都在Michael Hartls Ruby on Rails教程书的第3.6.1章中有所说明)。 [33]


最简单的方法是使用足够最新版本的RVM(>=1.11.x)。


如果你被限制在早期版本的RVM中,你总是可以使用calasyr也提到的这种方法:


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


然后bundler_stubs目录也应该添加到.gitignore文件中。


如果您不使用RVM,第三种选择是使用rubygems-bundler gem:


$ gem install rubygems-bundler
$ gem regenerate_binstubs

其它参考4


我没有使用bundle exec,但我现在正在设置它。


我曾经遇到过使用错误的rake的情况,浪费了很多时间来追踪问题。这有助于您避免这种情况。


这里是如何设置rvm,以便您可以在特定项目目录中默认使用bundle exec:


http://robots.thoughtbot.com/post/15346721484/use-bundlers-binstubs[35]

其它参考5


它意味着使用捆绑器知道的rake,并且是捆绑器不知道的任何rake的Gemfile的一部分,并运行db:migrate任务。

其它参考6


直接运行rake任务或执行gem的任何二进制文件时,无法保证命令的行为符合预期。因为您的系统上已安装了相同的gem,其版本说1.0,但在您的项目中,您的版本更高,即2.0。在这种情况下,您无法预测将使用哪一个。


要强制执行所需的gem版本,您需要bundle exec命令的帮助,该命令将在当前bundle的上下文中执行二进制文件。这意味着当您使用bundle exec时,bundler会检查为当前项目配置的gem版本并使用它来执行该任务。


我还写了一篇关于它的帖子,它也说明了我们如何避免使用bin存根。[36]