bundle exec rake db:migrate
是什么意思?或者只是一般的bundle exec rake <command>
?
我了解 bundle
负责维护 Gemfile 中的内容。我知道“执行”这个词是什么意思。我了解 rake
维护您可以执行的所有不同的脚本操作,并且我知道 db:migrate
就是其中之一。我只是不知道所有这些词在一起做什么。为什么要使用 bundle
执行 rake
来执行数据库迁移?
bundle exec
是一个 Bundler 命令,用于在当前捆绑包(您目录的 Gemfile 中的那个)的上下文中执行脚本。 rake db:migrate
是脚本,其中 db 是命名空间,migrate 是定义的任务名称。
因此 bundle exec rake db:migrate
在当前包的上下文中使用命令 db:migrate
执行 rake 脚本。
至于“为什么?”我将引用 bundler page:
在某些情况下,如果可执行文件恰好安装在您的系统中并且没有拉入任何与您的捆绑包冲突的 gem,则在没有 bundle exec 的情况下运行可执行文件可能会起作用。然而,这是不可靠的并且是相当大的痛苦的来源。即使它看起来可以正常工作,但将来或在另一台机器上可能无法正常工作。
您正在一个程序上运行 bundle exec
。该程序的创建者在某些版本的 gem 可用时编写了它。 Gemfile 程序指定了创建者决定使用的 gem 的版本。也就是说,脚本可以针对这些 gem 版本正确运行。
您的系统范围的 Gemfile 可能与此 Gemfile 不同。您可能有较新或较旧的 gem,而这个脚本不能很好地使用。这种版本的差异会给你带来奇怪的错误。
bundle exec
可帮助您避免这些错误。它使用脚本的 Gemfile 中指定的 gem 而不是系统范围的 Gemfile 来执行脚本。它使用 shell 别名的魔力执行某些 gem 版本。
在 the man page 上查看更多信息。
这是一个示例 Gemfile:
source 'http://rubygems.org'
gem 'rails', '2.8.3'
在这里,bundle exec
将使用 rails 版本 2.8.3 执行脚本,而不是您可能已在系统范围内安装的其他版本。
rake db:migrate
而忽略了 bundle exec
那么它将使用系统范围的 Gemfile 执行,其中一个可能有 1.5.2(最新)的机架?
bundle exec
在您的应用程序的 Gemfile 中使用“特定于应用程序”的本地 gem,如果您使用 gem install a_certain_gem
,则 bundle
使用“特定于机器”的全局 gem。本地与全球
当您的 gemfile.lock 在您的机器上安装了不同版本的 gems 时,这会出现很多。运行 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
告诉捆绑器执行此命令,而不管版本差异如何。并不总是有问题,但是,您可能会遇到问题。
幸运的是,有一个 gem 可以解决这个问题:rubygems-bundler。
$ gem install rubygems-bundler
$ $ gem regenerate_binstubs
然后再次尝试您的 rake、rspec 或其他任何东西。
可能应该提到,有一些方法可以省略 bundle exec
(它们都在 Michael Hartls Ruby on Rails Tutorial 书的第 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
当您直接运行 rake 任务或执行 gem 的任何二进制文件时,不能保证该命令将按预期运行。因为您可能已经在系统上安装了相同的 gem,其版本为 1.0,但在您的项目中,您的版本更高,例如 2.0。在这种情况下,您无法预测将使用哪一个。
要强制执行所需的 gem 版本,您需要 bundle exec
命令的帮助,该命令将在当前包的上下文中执行二进制文件。这意味着当您使用 bundle exec 时,bundler 会检查为当前项目配置的 gem 版本并使用它来执行任务。
我还写了一篇关于它的post,它还展示了我们如何避免使用 bin 存根来使用它。
bundle exec
我用的不多,但现在正在设置它。
我曾经遇到过使用错误的 rake 并且浪费大量时间来追踪问题的情况。这可以帮助您避免这种情况。
以下是设置 RVM 的方法,以便您可以在特定项目目录中默认使用 bundle exec
:
https://thoughtbot.com/blog/use-bundlers-binstubs
这意味着使用 bundler 知道的 rake 并且是 Gemfile 的一部分,而不是 bundler 不知道的任何 rake 并运行 db:migrate 任务。
bundle
是 Bundler 使用的命令。.ruby-gemset
文件时才适用。如果使用 RVM,还有一个.ruby-version
文件可以设置您的 ruby 版本。