30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

rbenv を使った Ruby のバージョン管理について

最初に環境を書いておくと、OSはmacOS High Sierra(10.13.5)
homebrewインストール済み。

RubyRailsを触り始めたのだが、初心者なのでとにかく躓く。
bundle installでエラー、rails newでエラー、rails sでエラー、foreman startでエラー……。
その都度調べて解決していくが、とにかく非効率。しかも、ネットの記事を見よう見真似でやっているだけで、何が起きているかよく分かっていない。

遠回りに思えても、ちゃんとRubyやパッケージ管理の仕組みを勉強しないとダメだなと感じた。
そもそもUnixの仕組み(ディレクトリ構成やパスやコマンドなど)をろくに分かっていないのが問題だが、それはまた別の話。

今回は、Rubyのバージョン管理について書いていく。
上述のエラーも、こういった環境構築が上手くいっていないことに起因するものが多いようだった。

rbenv

Macであれば、Rubyは最初から入っていることが多いはず。$ ruby -vでバージョンが表示されれば、Rubyが使える。
だが実際には、バージョン毎に仕様が違うため、それをそのまま使うのではなくRuby自体のバージョンを管理して開発することになるだろう。

今回はrbenvというツールを使ってRubyのバージョン管理を行う。

セットアップ

homebrewでインストールし、~/.bash_profileeval "$(rbenv init -)"という記述を追加。
$ source ~/.bash_profileで設定を反映させれば、完了。
ruby-buildも一緒にインストールする必要がある。

$ brew install rbenv ruby-build
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

$ rbenv --versionでバージョンが表示されれば成功である。ちなみにこれはRubyのバージョンではなくrbenvのバージョンなので注意。

ちなみに、インストールされたrbenv/usr/local/Cellar/rbenv/に入っている。
エラーメッセージなどでこのパスが出てきたときは、rbenvが関係しているかもしれない。

使い方

インストール可能なRubyの一覧は、$ rbenv install --listで確認できる。
大量に出てくるので、grepを使ったほうがいいかもしれない。

$ rbenv install --list | grep 2.5
  2.2.5
  2.5.0-dev
  2.5.0-preview1
  2.5.0-rc1
  2.5.0
  2.5.1
  rbx-2.2.5
  rbx-2.5.0
  rbx-2.5.1
  rbx-2.5.2
  rbx-2.5.3
  rbx-2.5.4
  rbx-2.5.5
  rbx-2.5.6
  rbx-2.5.7
  rbx-2.5.8

$ rbenv install バージョン名でインストールできる。

$ rbenv install 2.5.1
ruby-build: use openssl from homebrew
Downloading ruby-2.5.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.bz2
Installing ruby-2.5.1...
ruby-build: use readline from homebrew
Installed ruby-2.5.1 to /Users/$USER/.rbenv/versions/2.5.1

$ rbenv versionsとしたときにそのバージョンが表示されれば、インストール成功。
だがこの時点では、マシンにインストールしたというだけで、実際にそのバージョンが使用されるわけではない。

使用するバージョンを指定するには、$ rbenv global バージョン名とすればよい。
この状態で$ rbenv versionsとすると、指定したバージョンの前に*がついているはず。

$ rbenv versions
  system
* 2.5.1 (set by /Users/$USER/.rbenv/version)

が、これはあくまでもrbenvでの指定に過ぎない。設定が上手くいっていないこともあるので、$ ruby -vで確認したほうがよい。

$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]

正しくインストールされていることを確認できた。

ちなみに、Rubyのプログラムのなかでバージョンを取得したい場合は、RUBY_VERSIONを使う。

$ echo 'print RUBY_VERSION' > version.rb && ruby version.rb && rm version.rb
2.5.1

バージョンの適用

rbenvでは、ディレクトリ毎にRubyのバージョンを指定することが出来る。
$ rbenv global バージョン名で指定したのはマシン全体の設定。ディレクトリ毎の設定は$ rbenv local バージョン名で出来る。

予め$ rbenv install 2.5.02.5.0をインストールしておき、$ rbenv local 2.5.0としてみる。

$ rbenv local 2.5.0
$ rbenv versions
  system
* 2.5.0 (set by $PWD/.ruby-version)
  2.5.1
$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17]

2.5.0になっている。
と同時に、.ruby-versionというファイルが作られており、そこには2.5.0と書かれているのを確認できる。

$ ls -a
.       ..      .ruby-version
$ cat .ruby-version
2.5.0

実はrbenvでは、カレントディレクトリに.ruby-versionがないか探し、見つかれば、そこに書かれているバージョンを使う仕組みになっている。

見つからなかった場合、その親ディレクトリにないか確認する。これをルートディレクトリに辿り着くまで繰り返し、見つかった場合はその.ruby-versionに書かれているバージョンを適用する。

そして最後まで.ruby-versionが見つからなかった場合は/Users/$USER/.rbenv/versionに書かれているバージョンを適用する。
そしてそこには、$ rbenv globalで指定したバージョンが書かれている。

$ cat /Users/$USER/.rbenv/version
2.5.1

つまり$ rbenv loaclとは、指定したバージョンが書かれた.ruby-versionをカレントディレクトリに作成するコマンドであり、$ rbenv globalは指定したバージョンを/Users/$USER/.rbenv/versionに書き込むコマンドであると言える。

RBENV_VERSION

実はlocalでの指定よりもさらに優先される設定があり、それが環境変数RBENV_VERSIONである。
デフォルトは空で、$ rbenv shell バージョン名で指定できる。空に戻すには$ rbenv shell --unset

$ echo $RBENV_VERSION

$ rbenv shell 2.5.0
$ echo $RBENV_VERSION
2.5.0
$ rbenv shell --unset
$ echo $RBENV_VERSION

RBENV_VERSIONが指定されていると、その値が最優先される。

$ rbenv versions
  system
* 2.5.0 (set by RBENV_VERSION environment variable)
  2.5.1

だがこの値が設定されていると常にそのバージョンが採用されてしまい、ディレクトリ毎に設定することが出来なくなる。
基本的にはデフォルト設定である空のままでいいように思う。

参考資料