Railsのチュートリアルをやっていて、railsとbundleコマンドが使えない自体が発生しました。sporkを使った自動テストを設定している時でした。
第3章 ほぼ静的なページの作成 | Rails チュートリアル
常に使えないわけでなく、何故かターミナルを開いてさらにcmmand + tで新規端末を開いた場合に、その新しい端末だけでrvmコマンドが使えませんでした。railsとbundleは使えませんが、rvmは使うことが出来ました。
パスが通っていないのかと思い、両方の端末でecho $PATHで環境パスを確認。
# 使える方
/Users/mitsuru/.rvm/gems/ruby-2.0.0-p643/bin:/Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@global/bin:/Users/mitsuru/.rvm/rubies/ruby-2.0.0-p643/bin:/Users/mitsuru/.rvm/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
# 使えない方
/Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@railstutorial_rails_4_0/bin:/Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@global/bin:/Users/mitsuru/.rvm/rubies/ruby-2.0.0-p643/bin:/Users/mitsuru/.rvm/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
最初のパスだけ違います。使えない方のパスには@railstutorial_rails_4_0という文字がついていました。あれ?これはチュートリアルの最初のころに見たやつだ。そうだ、gemsetっていうものを設定したんだった。言われるがまま入力していたのよくありませんでしたね。ここでかなり泥沼にハマりました。しかし、今回のエラーでrvmについて勉強することができました。
今使われているrubyはどれだ?
rvmは確かrubyのバージョンを管理できるものとしか理解していません。そういえば今チュートリアルで作ったプロジェクト内にいるときはどのrubyを使っているのだろうと思いwhich rubyを実行
/Users/mitsuru/.rvm/rubies/ruby-2.0.0-p643/bin/ruby
どちらも同じrubyを使っていました。ruby自体に違いはないようです。次はrvm -vで調べてみることに。
rvm 1.26.11 (latest) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]
次も結果は同じでした。よく考えたらrvmは複数のruby(バージョン)を管理するツールなので、rubyはいくつもある可能性はありますが、rvmは普通にインストールしたら1つしか存在しないですね。
rvmは1つですが、rvmでインストールしたrubyはいくつあるのでしょうか?それはrvm listで知ることができます。これをホームディレクトリで実行してみると、
rvm rubies
=* ruby-2.0.0-p598 [ x86_64 ]
ruby-2.0.0-p643 [ x86_64 ]
- current
=* - current && default
* - default
いつのまにかrubyを2つインストールしていました。ちなみに、バージョンの後ろのpというのはパッチのpみたいです。
rubyバージョンのPって何よ? - Railsエラーノート
gemがないからコマンドが実行できない
今度はチュートリアルの作業場所、/Users/mitsuru/Desktop/work/rails_projects/sample_appに移動してrvm listを実行してみると、
rvm rubies
* ruby-2.0.0-p598 [ x86_64 ]
=> ruby-2.0.0-p643 [ x86_64 ]
使用しているrubyが変わっている!どういうことだ?何故かデフォルトであるp598は使われずに新しいパッチのp643が使われています。デフォルトは何も設定していない場合に使われるものだと思うので、私がいつのまにか後者を使うように設定していたのだろうか?
この使用バージョンの変更はruby useで行うことができます。rvm use 2.0.0ではruby-2.0.0-p643が優先されました。ruby-2.0.0-p598の時だけrvm use 2.0.0を実行すると切り替わります。パッチを指定しない場合は新しいものが選ばれるようです。
調べてみるとrailsとbundleコマンドが使えない理由は、ここに原因があることがわかりました。
実は rvm use してバージョンを切り替えると、環境変数の $PATH や $GEM_PATH がそれぞれのバージョンに併せたパスに書き換えられます。
今日から使える!rvmの簡単な使い方とその仕組み - (゚∀゚)o彡 sasata299's blog
環境変数の$PATHまで書き換わっているだと!?このrvmというのはrubyバージョンだけではなく実行環境もまでまるごと切り替えることができるのですね。これは便利です。
ここで1つ確認することがあります。gemはrubyのライブラリなどをパッケージにする時の形式で、gemコマンドでインストールすることができます。**そしてrailsとbundleもgemでインストールできます。つまりこの2つはのコマンドはgemだと推測しました。**ターミナルで使えるコマンド=gemと結びつかなかったのですが、よく考えるとこの2つのgemが入っていないからコマンドが使えないのです。
ではrvm gemset list_allでまず使われているgemsetを確認します。これはrvmでrubyのバージョンとgemの一覧を別々で管理して組み合わせられる機能です。
gemsets for ruby-2.0.0-p598 (found in /Users/mitsuru/.rvm/gems/ruby-2.0.0-p598)
(default)
global
=> railstutorial_rails_4_0
gemsets for ruby-2.0.0-p643 (found in /Users/mitsuru/.rvm/gems/ruby-2.0.0-p643)
(default)
global
=> railstutorial_rails_4_0
しかしgem listで実際に入っているgemを確認すると、使えない方は13個に対し使える方は90個。使えない方のgemlistを確認するとbundlerとrailsが無いことが判明。どっちもgemで管理していたのか。
どちらもgemsetは同じです。なのになぜインストールされているgemが違うのか?gem environmentで確認してみましょう。
# 使える方
RubyGems Environment:
- RUBYGEMS VERSION: 2.0.3
- RUBY VERSION: 2.0.0 (2014-11-13 patchlevel 598) [x86_64-darwin13.4.0]
- INSTALLATION DIRECTORY: /Users/mitsuru/.rvm/gems/ruby-2.0.0-p598@railstutorial_rails_4_0
- RUBY EXECUTABLE: /Users/mitsuru/.rvm/rubies/ruby-2.0.0-p598/bin/ruby
- EXECUTABLE DIRECTORY: /Users/mitsuru/.rvm/gems/ruby-2.0.0-p598@railstutorial_rails_4_0/bin
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-13
- GEM PATHS:
- /Users/mitsuru/.rvm/gems/ruby-2.0.0-p598@railstutorial_rails_4_0
- /Users/mitsuru/.rvm/gems/ruby-2.0.0-p598@global
- GEM CONFIGURATION:
省略
# 使える方
RubyGems Environment:
- RUBYGEMS VERSION: 2.0.3
- RUBY VERSION: 2.0.0 (2015-02-25 patchlevel 643) [x86_64-darwin13.4.0]
- INSTALLATION DIRECTORY: /Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@railstutorial_rails_4_0
- RUBY EXECUTABLE: /Users/mitsuru/.rvm/rubies/ruby-2.0.0-p643/bin/ruby
- EXECUTABLE DIRECTORY: /Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@railstutorial_rails_4_0/bin
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-13
- GEM PATHS:
- /Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@railstutorial_rails_4_0
- /Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@global
- GEM CONFIGURATION:
省略
GEM PATHSでgemがインストールされているディレクトリが分かります。各バージョンのgemsディレクトリ以下を確認したところ、~@globalにはrailsやbundlerはなく、さらに/Users/mitsuru/.rvm/gems/ruby-2.0.0-p643@railstutorial_rails_4_0/にはgemsというディレクトリ自体がないことを確認しました。
rubyのバージョン、gemsetのディレクトリは独立しているのかと思いましたがそうではなかったようです。rubyのバージョン+gemsetというディレクトリ名で管理されていました。
どちらのターミナルでもコマンドが使えなくなる
ここでrvm install 2.0.0を実行したら最初のターミナルでもrubyのバージョンが自動で切り替わり、railsとbundleが使えなくなりました。これはrvmのバグかなと思いrvm get latestでバージョンアップを確認。意味はありませんでした。rvm defaultでデフォルトのrubyをuse使用としたら、
Could not find ffi-1.9.8 in any of the sources
Run `bundle install` to install missing gems.
bundle
bundle installしろとのことなので実行してみると、なぜかrailsのコマンドが使えるように。これでGemsを再インストールしてくれたのだろうか?ただターミナルを再起動して、もう一度rvm listで確認するとまた新しいパッチのrubyに戻っています。そこでもう一度defaultに切り替えてrailsコマンドを実行すると、今度はbundleを実行しなくても使うことができました。
何故かホームディレクトリに戻るとrubyのバージョンがdefaultに戻ります。チュートリアルの作業ディレクトリだけでdefaultが効かないのです。
rvmを2回読み込んでいるとdefaultが効かない不具合が
rvmを2回読み込んでいるとdefaultが効かない不具合がでるらしいのでターミナル起動時にrvmをコマンドが実行されているか調べました。
ruby - Why doesn't "RVM --default" work for me on MacOSX? - Stack Overflow
# rvm .bash_profile
[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function *
# rvm .bashrc
# RVM
[ -s ${HOME}/.rvm/scripts/rvm ] && source ${HOME}/.rvm/script/rvm
etc/profileにはrvmという文字はなかったので、.bash_profileと.bashrcのrvmを実行する記述の直前にechoを出力するようにして、片方をコメントアウトしたり、両方をそのままにして試したところがechoが出力されたのは.bash_profileだけでした。どうやら2度読み込んでいることはなさそうです。
こうして色々と試していたのですが最終的にはrvm get headで直りました。やはりrvmの不具合だったのだろうか?ちなみにこのコマンドをhelpで引いてみると、 rvm get help head master - install the latest RVM development version
どうやら安定版ではなく開発版をインストールするようです。つい最近出ていたバグだったので、stableでは修正されなかったのかもしれません。
rvmが何かわからないなら、とにかくコマンドを打ちまくる
rvmはrubyのバージョンを管理するもの。というのは知っていましたが、あまりしっくりは来ませんでした。しかし、実際に今回の問題に出くわしログを見ながらひたすらコマンドを打つことによって前よりrvmについてイメージが持てました。実行環境を保存したディレクトリを管理していたのですね。
rvmのコマンドについては下記がサンプルもあり、大変参考になります。ですが、rvmと引数なしで打つとガイド(コマンドの説明)が出てきます。これが非常に端的にまとまっていますので、英語だからと流すのではなく、これを一度見てみるのが早期解決に繋がると思いました。実際に見てみると簡単な英語ばかりです。
rvm 入門 … 複数バージョンの Ruby と Rails を混在させる - まちゅダイアリー(2011-05-21)
結局、railsとbundleはgemという認識で合っているのだろうか?