Ruby on Rails 中的 Gemfile 和 Gemfile.lock 有啥区别

Posted

技术标签:

【中文标题】Ruby on Rails 中的 Gemfile 和 Gemfile.lock 有啥区别【英文标题】:What is the difference between Gemfile and Gemfile.lock in Ruby on RailsRuby on Rails 中的 Gemfile 和 Gemfile.lock 有什么区别 【发布时间】:2011-10-19 03:19:22 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

Gemfile 用于指定要使用的 gem,并允许您指定哪些版本。

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

查看Bundler's Purpose and Rationale,特别是检查您的代码到版本控制部分。

【讨论】:

这就是它应该工作的方式——但显然Gemfile.lock在某些情况下包括“开放”版本(例如rails (4.0.0)需要bundler (>= 1.3.0, < 2.0)),这会导致问题.知道如何避免那些“开放”依赖吗?【参考方案2】:

通常我们在 Gemfile 中写依赖为:

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

在这里你基本上说:“我想要 nokogiri,只要它高于 1.4.4 版”等等。现在假设我已经设置了我的 Gemfile8 个月前 我成功地按照这个要求设置了我的应用程序。 8 个月前 nokogiri 版本是 1.4.4。我的 Rails 应用程序运行完美,这个版本没有任何问题。

现在认为我正在尝试使用相同的 Gemfile 进行构建。但是如果我们查看nokogiri versions,我们会看到当前的稳定版本已更改为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 分发您的应用程序,每台机器都将安装相同的 gem,最重要的是 它们都将获得相同的版本。这将为您提供一个稳定且通用的部署堆栈。

Gemfile.lock 是如何创建的?

它是用第一个自动创建的:

bundle install

命令。之后每次运行bundle install,bundle 将首先查找Gemfile.lock 并安装那里指定的gem。在您的项目中分发此文件以提供一致和稳定性是一种习惯。

如何更新 Gemfile.lock?

如果您对最新版本的应用感到满意,可以更新Gemfile.lock。只需将您的更改反映到Gemfile。这意味着将依赖项更改为Gemfile 中的新版本。运行后:

bundle install

这将为您Gemfile.lock 更新您最新版本的应用程序。

【讨论】:

一个非常好的、清晰的描述(我赞成);但是,一个挑剔的人:nokogiri ~> 1.4.4 不允许安装1.5.3;允许的最大值为1.4.x,其中x>=4(对于nokogiri,为1.4.7)。 ~> 运算符意味着只有 last digit 中使用的 gem 可以“大于”给定版本。例如,foo ~> a.b.c.d 表示 foo 的任何版本都可以,只要它仍然是 a.b.c.something where something >= d。另见related question 令我困惑的是,您已经在 gemfile 中使用 gem "nokogiri", "~> 1.4.4" 指定了特定版本。为什么捆绑器不能只使用那个版本?是不是因为它的设计目的是默认安装最新版本的 gem? @Jonny,请参阅 michael_n 的评论。 ~> 1.4.4 没有指定确切的版本。 @Jonny, ~> 1.4.4 等价于>= 1.4.4 and < 1.5。见bundler.io/v1.5/gemfile.html。对于确切的版本,只需使用gem 'foo', '1.4.4' 很好的答案,但请澄清“update Gemfile.lock?”:这部分是否说bundle install 将检查Gemfile,即使有Gemfile.lock并对Gemfile.lock 实施新的限制?【参考方案3】:

Gemfile.lock

当您运行 bundle install 时,Bundler 会将您使用的所有 gem 的全名和版本(包括 Gemfile(5) 中指定的 gem 的依赖项)保存到一个名为 Gemfile.lock 的文件中。

Bundler 在所有后续调用 bundle install 时都使用此文件,这保证了您始终使用完全相同的代码,即使您的应用程序跨机器移动。

由于依赖解析的工作方式,即使是看似很小的更改(例如,更新 Gemfile(5) 中 gem 的依赖的点发布)都可能导致需要完全不同的 gem 来满足所有依赖项。

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

【讨论】:

以上是关于Ruby on Rails 中的 Gemfile 和 Gemfile.lock 有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 安装 JQuery

ruby on rails 中使用phantomjs,并使用cookie

ruby on rails 中使用pdfkit生成pdf

Ruby on Rails 上“...的预期字符串默认值”的含义

Ruby on Rails 上“...的预期字符串默认值”的含义

Ruby 中的“Gemfile”在哪里?