简体   繁体   English

我应该在我的Gemfile中指定确切的版本吗?

[英]Should I specify exact versions in my Gemfile?

I've noticed that on rubygems.org a lot of the gems suggest you specify them by major version rather than exact version. 我注意到在rubygems.org上有很多宝石建议你用主要版本而不是精确版本来指定它们。 For example... 例如...

The haml-rails gem ... haml-rails宝石 ......

gem "haml-rails", "~> 0.3.4"  # "$ bundle install" will acquire the 
                              # latest version before 1.0.

However, based on the Bundler docs it sounded to me like it would be better to nail down the exact version like this... 然而,根据Bundler文档,它听起来像我最好确定这样的确切版本...

gem "haml-rails", "0.3.4"

So there's your haml-rails gem and all its dependencies won't drift forward. 所以你的haml-rails gem和它的所有依赖都不会向前发展。 If you check out the project on a different machine a few weeks later and run $ bundle install you'll have precisely the same versions of everything you specified. 如果您在几周后在另一台机器上签出项目并运行$ bundle install那么您将拥有与您指定的所有内容完全相同的版本。

I've seen point releases break stuff, and I thought part of the whole idea of Bundler was to " Bundle.lock " all your gem versions. 我已经看到点发布破坏了东西,我认为Bundler的整个想法的一部分是“ Bundle.lock ”你所有的宝石版本。

But on rubygems.org they use "~>" a lot so maybe I'm missing something? 但是在rubygems.org上他们使用“〜>”很多,所以也许我错过了什么?

Any clarification would be very helpful to me in understanding Bundler and gem management. 任何澄清对我理解Bundler和gem管理都非常有帮助。

This is the purpose of the Gemfile.lock file - running bundle install with a Gemfile.lock present only installs using the dependencies listed in there; 这是Gemfile.lock文件的目的 - 使用Gemfile.lock运行bundle install只使用其中列出的依赖项进行安装; it doesn't re-resolve the Gemfile. 它不会重新解析Gemfile。 To update dependencies / update gem versions, you then have to explicitly do a bundle update , which will update your Gemfile.lock file. 要更新依赖项/更新gem版本,您必须显式执行bundle update ,这将更新您的Gemfile.lock文件。

If there wasn't a Gemfile.lock, deploying code to production would be a major issue because, as you mention, the dependencies and gem versions could change. 如果没有Gemfile.lock,将代码部署到生产将是一个主要问题,因为正如您所提到的,依赖项和gem版本可能会发生变化。

In short, you should be generally safe using the pessimistic version constraint operator ( ~> ) as rubygems.org advises. 简而言之,正如rubygems.org建议的那样,使用悲观版本约束运算符( ~> )通常应该是安全的。 Just be sure to re-run your tests after you do a bundle update to make sure nothing breaks. 确保在执行bundle update后重新运行测试以确保没有任何中断。

There's a nice article by Yehuda Katz that has a little more info on Gemfile.lock. Yehuda Katz有一篇很好的文章 ,它有更多关于Gemfile.lock的信息。

I would definitely say use the exact version numbers. 我肯定会说使用确切的版本号。 You can probably always just lock it down to a major version, or never specify any version, and be okay, but if you really want that fine grained level of control and to have 100% confidence in your program when being run on other machines, use the exact version numbers. 您可能总是将其锁定为主要版本,或者从不指定任何版本,并且没关系,但如果您真的想要这种精细的控制级别并且在其他计算机上运行时对程序有100%的信心,使用确切的版本号。

I've been in situations where the exact version number wasn't specified, and when I or someone else did a bundle install , the project broke because it went to a newer version. 我一直处在没有指定确切版本号的情况下,当我或其他人进行bundle install ,项目因为它进入了更新版本而破产。 This can be especially bad when deploying to production. 部署到生产时,这可能会特别糟糕。

Bundler does lock in your gem specifications, but if you're telling it to just use a major release, then it locks that in. So is just knows "Oh the version is locked in at > 0.1" or whatever, but not "Oh the version is locked in specifically at 0.1.2.3". Bundler 确实锁定了你的gem规范,但是如果你告诉它只是使用一个主要的版本,那么它将其锁定。所以只知道“哦版本被锁定在> 0.1”或者其他什么,但不是“哦该版本特别锁定在0.1.2.3“。

TL;DR TL; DR

Yes, use pessimistic locking ( ~> ) and specify a semantic version down to patch ( Major.minor.patch ) on all your gems! 是的,使用悲观锁定~> )并在所有宝石上指定一个语义版本到补丁( Major.minor.patch )!

Discussion 讨论

I am surprised by the lack of clarity on this issue, even "industry experts" told me the other day that Gemfile.lock is there to maintain gem versions. 我对这个问题缺乏明确感到惊讶,甚至“行业专家”前几天告诉我, Gemfile.lock是为了维护宝石版本。 Wrong! 错误!

You want to organize your Gemfile in such a manner that you can run bundle update any time without risking breaking everything. 您希望以这样的方式组织Gemfile ,以便您可以随时运行bundle update而不会破坏所有内容。 To achive this: 为了达到这个目的:

  1. Specify a patch-level version for all your gems with pessimistic locking. 为具有悲观锁定的所有宝石指定补丁级版本。 This will allow bundle update to give you fixes, but not breaking changes. 这将允许bundle update为您提供修复,但不会破坏更改。

  2. Specify a ref for gems from git 从git为gems指定一个ref

The only downside to this setup is that when a sweet new minor/major version for a gem comes out, you have to bump the version up manually. 这种设置的唯一缺点是,当一个宝石的新的小/主要版本出现时,你必须手动提升版本。

Warning scenario 警告方案

Consider what happens if you do not lock your gems. 考虑如果你没有锁定你的宝石会发生什么。
You have an unlocked gem "rails" in your gemfile and the version in Gemfile.lock is 4.1.16 . 你有一个解锁gem "rails"在你的Gemfile和版本Gemfile.lock4.1.16 You are coding along and at some point you do a bundle update . 您正在编码,并在某些时候进行bundle update Now your Rails version jumps to 5.2.0 (provided some other gem does not prevent this) and everything breaks. 现在你的Rails版本跳转到5.2.0 (如果其他一些宝石没有阻止这一点)并且一切都会中断。
Do yourself a favor and do not allow this for any gem! 帮自己一个忙,不要让任何宝石!

An example Gemfile Gemfile的一个例子

# lock that bundler
if (version = Gem::Version.new(Bundler::VERSION)) < Gem::Version.new('1.16.3')
  abort "Bundler version >= 1.16.3 is required. You are running #{version}"
end

source "http://rubygems.org"

# specify explicit ref for git repos
gem "entity_validator",
  git: "https://github.com/plataformatec/devise",
  ref: "acc45c5a44c45b252ccba65fd169a45af73ff369" # "2018-08-02"

# consider hard-lock on gems you do not want to change one bit
gem "rails", "5.1.5"

# pessimistic lock on your common gems
gem "newrelic_rpm", "~> 4.8.0"
gem "puma", "~> 3.12.0"

group :test do
  gem "simplecov", "~> 0.16.1", require: false
end

A concession 让步
If you are confident your tests will catch bugs introduced by gem version changes, you can try pessimistic-locking gems at minor version, not patch. 如果您确信您的测试将捕获宝石版本更改引入的错误,您可以尝试使用次要版本的悲观锁定宝石,而不是补丁。
This will allow the gem version to increase within the specified major version, but never into the next one. 这将允许gem版本在指定的主要版本中增加,但永远不会进入下一个版本。

gem "puma", "~> 3.12"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM