bundle exec rake db:migrate是什么意思?或者只是捆绑exec rake <命令>一般?

我知道这个bundle负责维护Gemfile中的东西。我知道"执行"是什么意思。我知道rake维护了您可以做的所有不同的脚本,我知道db:migrate就是其中之一。我只是不知道这些词在一起有什么用。为什么要使用bundle来执行rake来执行数据库迁移?


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


bundle exec是一个bundle命令,用于在当前bundle(来自您目录的Gemfile)的上下文中执行脚本。Rake db:migrate是脚本,其中db是命名空间,migrate是定义的任务名称。

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

至于“为什么?”我将引用捆绑页面上的话:

在某些情况下,如果可执行文件恰好安装在您的系统中,并且没有引入任何与您的包冲突的gem,那么运行没有捆绑包exec的可执行文件可能会工作。 然而,这是不可靠的,也是相当痛苦的来源。即使它看起来可以工作,但在将来或在另一台机器上可能无法工作。


我没有使用捆绑执行太多,但现在正在设置它。

我曾经使用过错误的耙子,浪费了很多时间来追踪问题。这可以帮助你避免这种情况。

下面是如何设置RVM,这样你就可以在特定的项目目录下默认使用bundle exec:

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


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

您的系统级Gemfile可能与此Gemfile不同。您可能有新的或旧的宝石,这个脚本不能很好地处理它们。版本之间的这种差异可能会导致奇怪的错误。

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

在手册页上查看更多信息。

这是一个Gemfile的例子:

source 'http://rubygems.org'

gem 'rails', '2.8.3'

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


应该提到的是,有很多方法可以忽略bundle exec(在Michael Hartls Ruby on Rails教程的3.6.1章中都有说明)。

最简单的方法是只使用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

这在你的gemfile中经常出现。Lock在您的机器上安装了不同版本的宝石。在运行rake(或rspec或其他)后,您可能会得到一个警告,例如:

您已经激活了rake 10.3.1,但是您的Gemfile需要rake 10.1.0。在你的命令前加上“bundle exec”可以解决这个问题。

预挂的bundle exec告诉绑定器不管版本差异都要执行这个命令。这并不总是一个问题,但是,您可能会遇到问题。

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

安装rubygems-bundler $ $ gem regenerate_binstubs

然后再试试你的rake, rspec,或者别的什么。


当您直接运行rake任务或执行gem的任何二进制文件时,不能保证该命令将按照预期的方式运行。因为可能发生的情况是,你的系统上已经安装了相同的gem,它的版本是1.0,但在你的项目中,你有更高的版本,比如2.0。在这种情况下,您无法预测将使用哪一个。

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

我也写了一篇关于它的文章,也展示了我们如何避免使用bin存根。