2021-07-10

ちゃんと理解するrbenv : (3) バージョン切り替えの仕組みを理解する

はじめに

本記事は、「ちゃんと理解するrbenv」の第3回です。
前回の記事

今回は、rbenvの機能の真髄であるバージョン切り替えの仕組みについて深堀りながら整理します。

バージョン切り替えのコマンドが裏でやっていること

バージョン切り替えに関わるコマンドとして、以下の3つがありました。

  • rbenv global
  • rbenv local
  • rbenv shell

この3つのコマンドが裏でやっていることをそれぞれ見ていきます。

rbenv global

rbenv global X.X.X を実行するとグローバルなRubyのバージョンを設定することは前回の記事で確認しました。

このコマンドを実行したとき、rbenvは ~/.rbenv 以下に version という名前のファイルを作成し、その中にバージョン情報をテキストで記録します。

実際に確認してみます。前回の記事の通りにコマンドを実行していれば、3.0.1がセットされているはずです。

// 現在のバージョンが3.0.1であることを確認
$ rbenv version
3.0.1 (set by /Users/mogulla3/.rbenv/version)

$ cat ~/.rbenv/version
3.0.1

このように、rbenv version の結果と一致する値が ~/.rbenv/version に書き込まれています。
ここで ~/.rbenv/version ファイルを削除するとどうなるか、試してみます。

$ rm ~/.rbenv/version

// 3.0.1からsystemになった
$ rbenv version
system (set by /Users/mogulla3/.rbenv/version)

rbenv version の結果が 3.0.1 -> system に変わりました。ここでもう一度 rbenv global コマンドを実行してみます。

$ rbenv global 3.0.1

$ cat ~/.rbenv/version
3.0.1

削除した ~/.rbenv/version ファイルが復活し、ファイルにも 3.0.1 が書き込まれていることがわかるかと思います。

rbenv local

rbenv local X.X.X を実行するとディレクトリ単位でRubyのバージョンを設定できました。

このコマンドを実行したとき、rbenvは .ruby-version というファイルをカレントディレクトリに作成し、その中にバージョン情報をテキストで記録します。

前回の記事で、myapp というディレクトリを作りそこで2.7.3を設定したと思います。そこを今一度見てみます。

$ cd myapp

$ rbenv version
2.7.3 (set by /Users/mogulla3/myapp/.ruby-version)

$ cat .ruby-version
2.7.3

myapp以下に .ruby-version ファイルが存在すること、そしてここで rbenv version を実行するとそのファイルの中身と同じバージョンになっていることがわかります。

ここで rbenv local を別バージョンで再実行してみます。

rbenv local 2.6.6

そして、.ruby-version ファイルを参照してみます。

$ cat .ruby-version
2.6.6

2.6.6に変わりました。rbenv local.ruby-version ファイルにバージョンを書き込んでいることがわかるかと思います。

rbenv shell

最後に rbenv shell です。このコマンドを実行するとシェル単位でRubyのバージョンを設定できました。

このコマンドを実行したとき、rbenvは RBENV_VERSION という環境変数にバージョン情報をセットします。
実際に確認してみます。

$ env | grep RBENV_VERSION
// => 結果なし

$ rbenv shell 2.7.3

$ env | grep RBENV_VERSION
RBENV_VERSION=2.7.3

このように、rbenv shell 実行前は環境変数 RBENV_VERSION は見つかりませんが、コマンド実行後は環境変数に値としてバージョンがセットされていることが見て取れます。

バージョン探索の優先順位がバージョンを決定する

ここまでで、3つのコマンドがやっていることがわかりました。

  • rbenv global : ~/.rbenv/version ファイルにバージョン情報を書き込む
  • rbenv local : .ruby-version ファイルにバージョン情報を書き込む
  • rbenv shell : RBENV_VERSION 環境変数にバージョン情報をセットする

どのコマンドもどこかしらにバージョン情報をセットしています。

rbenvのバージョン切り替えとはこうしてセットされたバージョン情報をある優先順位に従って探索し、最初に見つかったバージョンを利用しているだけなのです。

そして、バージョン探索の優先順位は次のようになっています。

バージョン探索の優先順位
バージョン探索の優先順位

すなわち..

  • (1) 環境変数 RBENV_VERSION がセットされているか?
    • あればバージョン決定
  • (2) .ruby-version ファイルがカレントディレクトリまたはその上の階層にあるか?
    • あればバージョン決定
  • (3) ~/.rbenv/version ファイルはあるか?
    • あればバージョン決定。もしなければ system とする

というロジックでバージョンが決まります。

rbenv version コマンドはどこでセットされたバージョンかを確認できる

これまでこの記事でも何度も使ってきた rbenv version コマンドですが、このコマンドの結果をよく見ると、どこでセットされたバージョンを利用しているかを確認できます。

コマンド実行結果のバージョン番号の後ろにある () の中身を見るとわかります。

// ~/.rbenv/version => グローバルなRubyバージョン
$ rbenv version
3.0.1 (set by /Users/mogulla3/.rbenv/version)

// .ruby-version => ローカルなRubyバージョン
$ rbenv version
2.6.6 (set by /Users/mogulla3/myapp/.ruby-version)

// 環境変数 => シェル固有のRubyバージョン
$ rbenv version
2.6.6 (set by RBENV_VERSION environment variable)

まとめ

本記事ではrbenvのバージョン切り替えの仕組みについて整理しました。

  • rbenv global、 rbenv local、 rbenv shell コマンドはどれもどこかにバージョン情報をセットしている
  • rbenvのバージョン切り替えとはセットされたバージョン情報を優先順位に従って探索し、最初に見つかったバージョンを利用している
  • 探索の優先順位は RBENV_VERSION > .ruby-version > ~/.rbenv/version となっている
  • rbenv version コマンドを見るとどこから設定されたバージョンかを確認できる