Ruby-on-rails 我应该在我的 Gemfile 中指定确切的版本吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9265213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 02:48:40  来源:igfitidea点击:

Should I specify exact versions in my Gemfile?

ruby-on-railsrubyruby-on-rails-3rubygemsbundler

提问by Ethan

I've noticed that on rubygems.org a lot of the gems suggest you specify them by major version rather than exact version. For example...

我注意到在 ruby​​gems.org 上,很多 gems 建议您按主要版本而不是确切版本指定它们。例如...

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 docsit 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. If you check out the project on a different machine a few weeks later and run $ bundle installyou'll have precisely the same versions of everything you specified.

所以有你的haml-rails gem,它的所有依赖都不会向前漂移。如果几周后$ 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”你所有的 gem 版本。

But on rubygems.org they use "~>" a lot so maybe I'm missing something?

但是在 ruby​​gems.org 上,他们经常使用“~>”,所以也许我遗漏了什么?

Any clarification would be very helpful to me in understanding Bundler and gem management.

任何澄清对我理解 Bundler 和 gem 管理都非常有帮助。

采纳答案by Abe Voelker

This is the purpose of the Gemfile.lock file - running bundle installwith a Gemfile.lock present only installs using the dependencies listed in there; it doesn't re-resolve the Gemfile. To update dependencies / update gem versions, you then have to explicitly do a bundle update, which will update your Gemfile.lock file.

这是 Gemfile.lock 文件的目的 -bundle install使用 Gemfile.lock运行仅使用此处列出的依赖项进行安装;它不会重新解析 Gemfile。要更新依赖项/更新 gem 版本,您必须显式执行 a 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. Just be sure to re-run your tests after you do a bundle updateto make sure nothing breaks.

简而言之,~>按照 ruby​​gems.org 的建议,使用悲观版本约束运算符 ( )通常应该是安全的。请务必在执行完之后重新运行测试bundle update以确保没有任何问题。

There's a nice articleby Yehuda Katz that has a little more info on Gemfile.lock.

有一个很好的文章由耶胡达·卡茨说,对Gemfile.lock的多一点信息。

回答by Epigene

TL;DR

TL; 博士

Yes, use pessimistic locking(~>) and specify a semantic versiondown to patch (Major.minor.patch) on all your gems!

是的,使用悲观锁定( ~>) 并在所有 gem 上指定一个语义版本到补丁 ( 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.lockis there to maintain gem versions. Wrong!

我对这个问题缺乏明确性感到惊讶,甚至“行业专家”前几天告诉我,Gemfile.lock那里可以维护 gem 版本。错误的!

You want to organize your Gemfilein such a manner that you can run bundle updateany time without risking breaking everything. To achive this:

您希望以Gemfile一种可以随时运行bundle update而不会破坏一切的方式来组织您的活动。要实现这一点:

  1. Specify a patch-level version for all your gems with pessimistic locking. This will allow bundle updateto give you fixes, but not breaking changes.

  2. Specify a reffor gems from git

  1. 使用悲观锁定为所有 gem 指定补丁级别版本。这将允许bundle update为您提供修复,但不会破坏更改。

  2. ref为来自 git 的 gems指定一个

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.

这种设置的唯一缺点是,当一个 gem 的新的次要/主要版本出现时,您必须手动提高版本。

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.lockis 4.1.16. You are coding along and at some point you do a bundle update. Now your Rails version jumps to 5.2.0(provided some other gem does not prevent this) and everything breaks.
Do yourself a favor and do not allow this for any gem!

考虑一下如果您不锁定您的宝石会发生什么。
gem "rails"的 gemfile 中有一个已解锁,并且其中的版本Gemfile.lock4.1.16. 您正在编码并在某些时候执行bundle update. 现在您的 Rails 版本跳转到5.2.0(假设其他一些 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 版本更改引入的错误,你可以尝试在次要版本而不是补丁上使用悲观锁定 gems。
这将允许 gem 版本在指定的主要版本内增加,但永远不会增加到下一个。

gem "puma", "~> 3.12"

回答by MrDanA

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. This can be especially bad when deploying to production.

我遇到过没有指定确切版本号的情况,当我或其他人执行bundle install. 这在部署到生产时尤其糟糕。

Bundler doeslock 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.2.3"。