Ruby on Rails 中 Gemfile 和 Gemfile.lock 有什么区别?

146

我是一个Ruby on Rails的初学者,目前正在使用Rails 3.0.9。

GemfileGemfile.lock在Rails中有什么区别?

3个回答

189

Gemfile 文件用于指定你要使用哪些gem,并允许你指定它们的版本。

Gemfile.lock 文件是Bundler记录安装的确切版​​本的地方。这样,当在另一台机器上加载相同的库/项目时,运行bundle install将查看Gemfile.lock并安装完全相同的版本,而不仅仅是使用Gemfile和安装最新版本。(在不同的机器上运行不同的版本可能会导致测试失败等问题。)您不应直接编辑lock文件。

请查看 Bundler的目的和基本原理,特别是“将您的代码检入版本控制”部分。


2
这就是它应该的工作方式 - 但显然,某些情况下Gemfile.lock包括“开放”的版本(例如,rails(4.0.0)需要bundler(>= 1.3.0,<2.0)),这会导致问题。有任何想法来避免这些“开放”依赖关系吗? - Guillermo Grau

176

通常我们将依赖项写在 Gemfile 中:

gem "nokogiri", "~> 1.4.4"
gem 'bcrypt-ruby', '~> 3.0.0'
gem 'uglifier', '>= 1.2.3'
..

这里你基本上是在说:“只要nokogiri的版本大于1.4.4,我就想要它”,等等。现在假设我8个月前设置了我的Gemfile并成功地使用了这个要求来设置我的应用程序。8个月前nokogiri的版本是1.4.4。我的rails应用程序正常运行,没有任何问题。

现在假设我尝试使用相同的Gemfile构建。但是如果我们查看nokogiri的版本,我们会发现当前稳定版本已经更新到了1.4.9。这意味着如果我们试图构建,bundler将安装nokogiri的1.4.9版本(假设我们没有Gemfile.lock)。

这意味着什么?

正如您所看到的,如果您没有任何Gemfile.lock并运行:

bundle install

当前使用的宝石随时可能会有所不同。您的应用程序使用版本 1.4.4,并且在8个月前没有任何问题,但是如果您现在尝试构建它,您将得到版本 1.4.9 。也许它在nokogiri的最新版本中出了问题,您使用的很棒的功能在 1.4.4 中已不再可用等等。

为了防止这种问题,使用Gemfile.lock。在Gemfile.lock中仅编写确切的版本,因此只会安装这些版本。这意味着如果您使用Gemfile.lock分发应用程序,则每台机器都会安装相同的宝石,而最重要的是它们都获得相同的版本。这将为您提供稳定和共同的部署栈。

如何创建Gemfile.lock?

它是通过第一个命令自动创建的:

bundle install

每次运行bundle install命令时,都会首先查找Gemfile.lock并安装其中指定的gems。将此文件分发到您的项目中可以提供一致性和稳定性,这是一种习惯。

如何更新Gemfile.lock?

如果您满意应用程序的最新版本,则可以更新Gemfile.lock。只需在Gemfile中反映出您的更改即可,也就是将依赖项更改为Gemfile中的新精确版本。之后运行:

bundle install

这将使用您的最新应用版本更新Gemfile.lock


27
一个非常好的、清晰的描述(我已经点赞了);但是有一个小问题:nokogiri ~> 1.4.4 不允许安装 1.5.3,最大允许的版本是 1.4.x,其中 x>=4(对于 nokogiri 来说,这将是 1.4.7)。~> 运算符表示只能使用 gem 中的 最后一位数字 大于给定版本。例如,foo ~> a.b.c.d 表示任何版本的 foo 都可以,只要它仍然是 a.b.c.{something},其中{something} >= d。另请参见 相关问题 - michael
1
让我感到困惑的是,你已经在Gemfile中使用了gem "nokogiri", "~> 1.4.4"来指定特定版本(或版本范围)。那么为什么Bundler不能直接使用该版本呢?难道这是因为它默认会有意地安装最新版本的gem吗? - Jonny
@Jonny,请看michael_n的评论。1.4.4没有指定确切的版本。 - Matthew Flaschen
2
@Jonny,~> 1.4.4 相当于 >= 1.4.4 and < 1.5。请参阅 http://bundler.io/v1.5/gemfile.html 。要使用精确版本,请使用 gem 'foo','1.4.4' - Matthew Flaschen
2
非常好的回答,但请澄清“更新Gemfile.lock?”:这一部分是否在说即使有Gemfile.lockbundle install也会检查Gemfile并对Gemfile.lock强制执行新的限制? - JMess
显示剩余3条评论

6

Gemfile.lock

当你运行 bundle install 时,Bundler 将记录所使用的所有 gem 的完整名称和版本(包括 Gemfile(5) 中指定的 gem 的依赖关系)到一个名为 Gemfile.lock 的文件中。

Bundler 在每次调用 bundle install 时都会使用此文件,以确保您始终使用完全相同的代码,即使您的应用程序在不同的机器上移动也是如此。

由于依赖关系解析的方式,即使看似很小的更改(例如,Gemfile(5) 中某个 gem 的依赖项的点发行版更新)也可能导致需要使用完全不同的 gem 来满足所有依赖项。

因此,您应该将 Gemfile.lock 检入版本控制。如果没有检入版本控制,则检出您的存储库的每台机器(包括生产服务器)都将重新解析所有依赖项,这将导致使用不同版本的第三方代码,如果 Gemfile(5) 中的任何 gem 或其依赖项已更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接