2022-06-12

Gemfileで使われる ~> はなにを意味するか

Gemfileにてgemのバージョン指定に使われる ~> という記号が示すバージョンの範囲が覚えられないので整理した。

最初に結論

  • メジャーバージョンのみ指定した場合、指定したメジャーバージョンの最新版が入る
  • マイナーバージョンまで指定した場合、メジャーバージョンを維持しつつ、指定したマイナーバージョン以上の最新版が入る
  • パッチバージョンまで指定した場合、マイナーバージョンを維持しつつ、指定したパッチバージョン以上の最新版が入る

具体例を上げると次のようになる。

  • ~> 12.0 > x >= 1.0 と同義
  • ~> 1.02.0 > x >= 1.0 と同義
  • ~> 1.0.01.1 > x >= 1.0.0 と同義

※ 個人的覚え方: 一番右のドット . より左のバージョンは維持される。ドットがない場合はそのバージョンが維持される。

名称

~> という記号は

  • pessimistic operator
  • twiddle wakka

などと呼ばれているようだ。名前を知っておくと検索しやすくなるので覚えておこう。

実際に試してみた

試すgemはなんでもよかったが、rackはいい感じに色々なバージョンがあったので rack を使って検証した。

rackのバージョン一覧 (2022年6月12日時点)
2.2.3.1
2.2.3
2.2.2
2.2.1
2.2.0
2.1.4.1
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.9.1
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0.rc1
2.0.0.alpha
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0.beta2
1.6.0.beta
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0.beta.2
1.5.0.beta.1
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.10
1.3.9
1.3.8
1.3.7
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.3.0.beta2
1.3.0.beta
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.1.pre
1.1.0
1.0.1
1.0.0
0.9.1
0.9.0
0.4.0
0.3.0
0.2.0
0.1.0

※ 検証環境

$ ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [arm64-darwin21]

$ bundle -v
Bundler version 2.3.15

Gemfileに gem 'rack', '~> x' と記述し、x の部分を変えながら bundle install をして bundle list rack でバージョンを確認した。以下はその結果。

Gemfileの記述 installされたバージョン 補足
~> 0 0.9.1 1.0 > x >= 0.0 なので、0系の最新が入る
~> 1 1.6.13 2.0 > x >= 1.0 なので、1系の最新が入る
~> 2 2.2.3.1 3.0 > x >= 2.0 なので、2系の最新が入る
~> 0.0 0.9.1 1.0 > x >= 0.0 なので、0系の最新が入る
~> 1.0 1.6.13 2.0 > x >= 1.0 なので、1系の最新が入る
~> 2.0 2.2.3.1 3.0 > x >= 2.0 なので、2系の最新が入る
~> 2.0.0 2.0.9.1 2.1 > x >= 2.0.0 なので、2.0系の最新が入る
~> 2.0.1 2.0.9.1 2.1 > x >= 2.0.1 なので、2.0系の最新が入る
~> 2.1.0 2.1.4.1 2.2 > x >= 2.1.0 なので、2.1系の最新が入る
~> 2.1.1 2.1.4.1 2.2 > x >= 2.1.1 なので、2.1系の最新が入る
~> 2.2.0 2.2.3.1 2.3 > x >= 2.2.0 なので、2.2系の最新が入る
~> 2.2.1 2.2.3.1 2.3 > x >= 2.2.1 なので、2.2系の最新が入る

~> 0~> 0.0 の違いについて考察

~> 0~> 0.01.0 > x > 0.0 となり、意味は全く同じとなる。

後者はマイナーバージョンを指定するのだから、「0.2以上じゃないとだめ」というようにマイナーバージョンの下限に制限がある場合に使うのが良いだろう。なので ~> 0.1~> 0.2 といった指定は良いが、~> 0.0 のようにマイナーバージョンが最低値になる指定は意図がわかりにくいのでイマイチな指定方法だと思う。

「0系であればなんでもよい」という状態であれば ~> 0.0 より ~> 0 の方がより意味が伝わりやすい。

感想

一言でいうと、わかりづらいなぁ...という感想。

この記事を書く過程で、関連するいくつかのブログ記事を読んだが、間違った内容の記事も結構見つかった。自分もすぐに忘れそう。
gem 'rack', '~> 2.0.0' とするなら gem 'rack', '>= 2.0.0', '< 2.1' と書いたほうがわかりやすい。

このバージョン指定子は Pessimistic operator という名前にも表れているように、バージョンの上限を制限したい場合に使うべきものなので、gemを利用することが主になるアプリケーション開発者はそこまで使う機会は多くない気がする。とはいえ、意味を理解して読めるようにはなっておくのは大事だ。

参考