bundle exec rake db:migrate是什么意思?或者只是捆绑exec rake <命令>一般?
我知道这个bundle负责维护Gemfile中的东西。我知道"执行"是什么意思。我知道rake维护了您可以做的所有不同的脚本,我知道db:migrate就是其中之一。我只是不知道这些词在一起有什么用。为什么要使用bundle来执行rake来执行数据库迁移?
bundle exec rake db:migrate是什么意思?或者只是捆绑exec rake <命令>一般?
我知道这个bundle负责维护Gemfile中的东西。我知道"执行"是什么意思。我知道rake维护了您可以做的所有不同的脚本,我知道db:migrate就是其中之一。我只是不知道这些词在一起有什么用。为什么要使用bundle来执行rake来执行数据库迁移?
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存根。