web-dev-qa-db-ja.com

Gemfileで正確なバージョンを指定する必要がありますか?

Rubygems.orgでは、多くのgemが、正確なバージョンではなく、メジャーバージョンで指定することを示唆していることに気付きました。例えば...

haml-Rails gem ...

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

ただし、 Bundler docs に基づいて、このような正確なバージョンを特定する方が良いと思われました...

gem "haml-Rails", "0.3.4"

そのため、haml-Rails gemがあり、その依存関係がすべて先に進むことはありません。数週間後に別のマシンでプロジェクトをチェックアウトし、$ bundle install指定したすべてのものとまったく同じバージョンになります。

ポイントリリースで問題が発生するのを見てきましたが、Bundlerのアイデア全体の一部は「Bundle.lock "すべてのgemバージョン。

しかし、rubygems.orgでは「〜>」を頻繁に使用するため、何かが足りないのではないでしょうか。

明確化は、Bundlerとgemの管理を理解する上で非常に役立ちます。

62
Ethan

これがGemfile.lockファイルの目的です-Gemfile.lockでbundle installを実行すると、そこにリストされている依存関係を使用したインストールのみが存在します。 Gemfileを再解決しません。依存関係を更新/ gemバージョンを更新するには、bundle updateを明示的に実行する必要があります。これにより、Gemfile.lockファイルが更新されます。

Gemfile.lockがなければ、コードを実稼働環境に展開することは大きな問題になります。これは、言及したように、依存関係とgemバージョンが変わる可能性があるためです。

要するに、rubygems.orgが推奨しているように、悲観的なバージョン制約演算子(~>)を使用すると、一般的に安全であるはずです。 bundle updateを実行した後に必ずテストを再実行して、問題が発生しないことを確認してください。

Yehuda Katzによる Nice article があり、Gemfile.lockについてもう少し情報があります。

55
Abe Voelker

正確なバージョン番号を使用することは間違いありません。おそらく常にメジャーバージョンにロックダウンするか、バージョンを指定しないで大丈夫ですが、その細かなレベルの制御を本当に望み、他のマシンで実行されているときにプログラムに100%の信頼を持たせたい場合は、正確なバージョン番号を使用してください。

正確なバージョン番号が指定されていない状況で、私または他の誰かがbundle install、新しいバージョンに移行したため、プロジェクトは中断しました。これは、実稼働環境にデプロイするときに特に悪い場合があります。

Bundler does gem仕様をロックしますが、メジャーリリースのみを使用するように指示している場合、ロックします。「Oh the version is in in the 0.1」または何でも、「ああ、バージョンは具体的に0.1.2.3でロックされています」ではありません。

6
MrDanA

TL; DR

はい、すべてのgemで ペシミスティックロック~>)を使用し、 セマンティックバージョン をパッチ(Major.minor.patch)に指定します。

ディスカッション

先日、「業界の専門家」でさえ、Gemfile.lockがgemバージョンを維持するためにあると私に言った。違う!

Gemfileを整理して、すべてを壊すことなくbundle updateをいつでも実行できるようにします。これを実現するには:

  1. ペシミスティックロックを使用して、すべてのgemのパッチレベルバージョンを指定します。これにより、bundle updateによる修正が可能になりますが、変更は壊されません。

  2. Gitのgemにrefを指定します

このセットアップの唯一の欠点は、gemの甘い新しいマイナー/メジャーバージョンが出てきたときに、手動でバージョンを上げる必要があることです。

警告シナリオ

Gemをロックしないとどうなるかを考えてください。
gemfileにgem "Rails"のロックが解除されており、Gemfile.lockのバージョンは4.1.16です。一緒にコーディングしていて、ある時点でbundle updateを実行します。これでRailsバージョンが5.2.0にジャンプします(他のgemがこれを妨げない場合)とすべてが壊れます。
あなた自身に感謝し、宝石にこれを許可しないでください!

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

譲歩
gemバージョンの変更によって導入されたバグをテストで検出できると確信している場合は、パッチではなくマイナーバージョンでpessimistic-locking gemを試すことができます。
これにより、指定したメジャーバージョン内でgemバージョンを増やすことができますが、次のバージョンには決してできません。

gem "puma", "~> 3.12"
4
Epigene