
【Ruby on Rails】The `rails' command exists in these Ruby versions エラーの解決方法
rbenvでRubyのバージョンを切り替えた直後、rails --version を実行したら次のエラーが出ました。
The `rails' command exists in these Ruby versions:
2.x.x
「railsはインストールしたはずなのに使えない」という状況です。当時の環境はRuby 2.5.1 / Rails 6.0.0で、手順自体は現行バージョンでも同様に動作します。結論から言うと、gem install rails を現在のバージョン向けに実行し直すだけで解決します。
なぜこのエラーが起きるのか
rbenvやrvmはRubyのバージョンを切り替える仕組みですが、gemはRubyのバージョンごとに独立して管理されています。あるバージョンにインストールしたgemは、別のバージョンからは参照できません。
つまりエラーメッセージの意味は「railsコマンドは別のRubyバージョンには存在するが、今使っているバージョンにはインストールされていない」ということです。バージョンを切り替えたタイミングで、新しいバージョン向けのgemが存在しない状態になっています。
gemがバージョンごとに独立している理由
RubyのC拡張を含むgemは、Rubyのバージョンに依存したネイティブコードをコンパイルして生成します。あるバージョン向けにビルドしたバイナリは別バージョンのRubyでは動きません。純粋なRubyコードだけのgemであっても、rbenvはgemのパスを ~/.rbenv/versions/<version>/lib/ruby/gems/ 以下にバージョン別で管理するため、他バージョンのgem置き場は参照されません。
rbenvでの実際のパス構造を確認するとこうなります。
$ rbenv which gem
/Users/yourname/.rbenv/versions/3.2.0/bin/gem
$ gem env home
/Users/yourname/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0
バージョンを切り替えると rbenv which gem の出力が変わり、別のディレクトリを参照するようになります。前のバージョンでインストールしたgemはそのまま別パスに残っているため、gem list を旧バージョンで確認すると今まで入れたgemが見えますが、新バージョンに切り替えると全て消えたように見えます。
解決手順
現在使用しているRubyバージョンにrailsを再インストールします。
$ gem install rails
インストール完了後、コマンドが使えるか確認します。
$ rails --version
Rails 6.0.0
rbenvを使っている場合、gemのインストール後に rbenv rehash が必要なこともあります。シェルがコマンドのパスを更新するためのコマンドです。
$ rbenv rehash
Bundlerを使ったプロジェクトに入る場合は、あわせて bundle install も実行しておくとよいです。プロジェクトが依存するgemを新しいRubyバージョン向けに揃えられます。
rbenv rehash が必要な理由
rbenvはシェルに rbenv shims のディレクトリをPATHに追加することで動作します。rails コマンドは実際には shims ディレクトリ内の小さなラッパースクリプトであり、呼び出し時に現在のRubyバージョンに対応する本物の rails を見つけて実行します。
新しいgemをインストールしても、この shims が自動で更新されないケースがあります。rbenv rehash を実行すると ~/.rbenv/shims/ ディレクトリが再生成され、インストールしたgemのコマンドが正しく参照されるようになります。
# shims の中身を確認する
ls ~/.rbenv/shims/ | grep rails
# => rails(存在しなければ rehash が必要)
現行バージョンのrbenvでは gem インストール後に自動で rehash が走るよう改善されているケースもありますが、動かない場合は手動で実行するとよいです。
バンドラー(Bundler)との関係
プロジェクトに Gemfile がある場合、単に gem install rails でグローバルにインストールするよりも bundle install でプロジェクト内の依存を揃える方が推奨されます。
# プロジェクトディレクトリで
$ bundle install
# bundle exec 経由でコマンドを実行する
$ bundle exec rails --version
bundle exec をつけると Gemfile.lock に記載されたバージョンのgemが優先して使われます。グローバルにインストールした別バージョンのrailsとの混在を防げます。
Gemfile.lock にはgemのバージョンだけでなく、RUBY VERSION として動作確認済みのRubyバージョンも記録されます。バージョン切り替え後にこのエントリが現在のバージョンと合わない場合は bundle update --ruby で更新できます(バージョンによって挙動が異なるため確認してから実行してください)。
同種のエラーへの応用
このエラーを理解すると、同じ原因で起きる類似エラーに対処できます。
The 'rake' command exists in these Ruby versions:gem install rakeで対応The 'bundler' command exists in these Ruby versions:gem install bundlerで対応rspecやpumaなど他のコマンドでも同様
バージョン切り替え直後に複数のコマンドが使えなくなった場合、まず gem list で現在のバージョン向けにどのgemが入っているか確認するとよいです。
$ gem list
# 何も(または少ししか)入っていなければ、新バージョン向けの gem が未インストール
よく使うgemをまとめてインストールしたい場合は、以下のようにまとめて実行できます。
$ gem install rails bundler rubocop
$ rbenv rehash
また .ruby-version ファイルをプロジェクトルートに置いておくと、そのディレクトリに入った時点でrbenvが自動的に指定バージョンに切り替えます。バージョン管理を明示的にしておくと、チーム開発やCI環境でのバージョン不一致を防ぎやすくなります。
# プロジェクトルートに .ruby-version を作成
$ echo "3.2.0" > .ruby-version
# そのディレクトリに入ると自動でバージョンが切り替わる
$ ruby --version
ruby 3.2.0 ...
参考ドキュメント
rbenvの詳細なコマンドリファレンス(バージョン切り替え・shims・rehashの仕組みなど)は公式リポジトリを参照してください。
GitHub - rbenv/rbenv: Manage your app's Ruby environment
Manage your app's Ruby environment. Contribute to rbenv/rbenv development by creating an account on GitHub.
gemのインストールと管理の基本(gem install / gem list / gem uninstall の動作)はRubyGemsの公式ガイドにまとまっています。
RubyGems Basics - RubyGems Guides
Tutorials, guides, FAQs for RubyGems package management
BundlerとGemfile、bundle install / bundle exec の使い方はBundlerの公式ドキュメントを参照してください。
Bundler: The best way to manage a Ruby application's gems
記事の更新をメールで受け取る
質問・リクエストを送る
記事についての質問や、取り上げてほしいテーマがあればお気軽にどうぞ。いただいた質問はブログ記事として回答し、Q&Aページで公開することがあります。