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 中的Gemfile
和Gemfile.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 版”等等。现在假设我已经设置了我的 Gemfile
8 个月前 我成功地按照这个要求设置了我的应用程序。 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 中使用phantomjs,并使用cookie
Ruby on Rails 上“...的预期字符串默认值”的含义