Rails

Railsチュートリアルでrails newするときはバージョンを指定しよう

More than 3 years have passed since last update.

よく起きる問題

Railsチュートリアルでサンプルアプリケーションを作っていくと、以下のエラーに遭遇する人が結構いるみたいです。

`require': cannot load such file -- active_job/railtie (LoadError)

おそらく同じエラーで困っている方の例

手っ取り早く原因と解決策を知りたい方へ

上のようなエラーはrails newするときにRails 4.2が実行されたために発生します。

そこでRailsチュートリアルで使われているRailsと同じバージョンが実行されるよう、rails newコマンドを打ち込むときに必ずバージョンを指定してください。

※注:この記事の執筆時点のRailsチュートリアルでは Rails 4.0.5 が使われています。

http://railstutorial.jp/chapters/beginning?version=4.0#sec-install_rails

第1章 1.2.3最初のアプリケーション

http://railstutorial.jp/chapters/beginning?version=4.0#sec-the_first_application

# rails new first_app
# ではなく
$ rails _4.0.5_ new first_app

第2章 2.1 アプリの計画

http://railstutorial.jp/chapters/a-demo-app?version=4.0#sec-planning_the_application

# rails new demo_app
# ではなく
$ rails _4.0.5_ new demo_app

第3章 ほぼ静的なページの作成

http://railstutorial.jp/chapters/static-pages?version=4.0#top

# rails new sample_app --skip-test-unit
# ではなく
$ rails _4.0.5_ new sample_app --skip-test-unit

なぜバージョンを指定する必要があるのか?

gemは1つのPCに複数のバージョンをインストールすることができます。
rails newを実行したときはデフォルトで最新バージョンのRailsが起動します。
もし、あなたのPCにRails 4.2が入っていると、rails newしたときはRails 4.0.5ではなく、Rails 4.2が実行されます。
4.0系と4.2系では生成されるファイルの構成が異なり互換性がないため、Railsチュートリアルを進めていくときに思わぬエラーに遭遇します。

インストールされているRailsのバージョンを確認する方法

以下のコマンドでインストールされているRailsのバージョンを確認できます。

$ gem search ^rails$ -l

*** LOCAL GEMS ***

rails (4.2.0, 4.1.9, 4.1.8, 4.0.5)

上の実行例のように、4.2系のRailsが最新バージョンになっている場合はrails newしたときにRails 4.2が起動します。

$ rails -v
Rails 4.2.0

Rubyのバージョンが変わるとインストールされているgemも変わる

rbenvやRVMを使ってRubyのバージョンを切り替えると、それぞれのバージョンでインストールされているgemのバージョンも異なります。

下は僕のマシンでRubyのバージョンを切り替えたときの実行例です。
Ruby 2.2.1だとRails 4.2.0が最新ですが、Ruby 2.1.5に変えるとRails 4.1.8が最新になっています。

$ ruby -v
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]

$ gem search ^rails$ -l

*** LOCAL GEMS ***

rails (4.2.0, 4.1.9, 4.1.8)

$ rbenv shell 2.1.5 
$ ruby -v              
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]

$ gem search ^rails$ -l

*** LOCAL GEMS ***

rails (4.1.8, 4.1.7, 4.1.1, 4.1.0)

「自分はRails 4.0.5しかインストールしていないからバージョンを指定しなくても大丈夫だ」と思っていても、Rubyのバージョンを切り替えたときには状況が変わっている可能性があります。
こういったgemの挙動に注意しましょう。

Railsアプリのディレクトリにいるかどうかでrails -vのバージョンが変わる

あとついでにもう一点。
rails -vでRailsのバージョンを確認する場合も注意が必要です。

以下の実行例を見てください。

# ホームディレクトリでバージョンを確認する
$ cd ~
$ rails -v
Rails 4.2.0

# Railsアプリのディレクトリに移動してからバージョンを確認する
$ cd ~/dev/my_app
$ rails -v
Rails 4.1.9

このようにカレントディレクトリの状況によって、rails -vの実行結果が異なります。

詳しい話は省略しますが、Railsアプリのディレクトリにいる場合はそのアプリで使用しているRailsのバージョンが、それ以外の場合はインストールされているRailsの最新バージョンがそれぞれ表示されます。

このあたりの挙動について詳しく知りたい場合はこちらの記事を参考にしてみてください。

rails newするときに --skip-test-unit オプションを付けるとapplication.rbの内容が変わる

さらにさらに、冒頭に書いた`require': cannot load such file -- active_job/railtie (LoadError)のエラーは、おそらく第3章以降で発生するんじゃないかと思います。

それはなぜかというと、第3章ではrails newするときに--skip-test-unitオプションを付けるからです。

これを付けるとconfig/application.rbの内容が若干変わります。

# オプション無しの場合(Rails 4.2.0)
require File.expand_path('../boot', __FILE__)

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module SampleApp
  class Application < Rails::Application
  # 以下省略
# --skip-test-unit オプションありの場合(Rails 4.2.0)
require File.expand_path('../boot', __FILE__)

# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module SampleApp
  class Application < Rails::Application
  # 省略

見比べてもらうとわかりますが、--skip-test-unitオプションを付けるとrequire 'rails/all'ではなく、個別にフレームワークをrequireするようになります。

require 'rails/all'であれば、Railsのバージョンが違っても「Railsにお任せ」できるので無効なフレームワークは読み込まれません。
しかし、個別にフレームワークをrequireする場合にはactive_jobのようなバージョンに依存するフレームワークが登場してしまい、バージョンが異なるRailsで起動しようとすると「そんなもんねーよ」とRailsに怒られてしまいます。
つまりそれが cannot load such file -- active_job/railtie の意味する内容です。

まとめ

こういったバージョンの扱いはなかなかややこしいですね。
僕も最初の頃はあまりよくわかっていませんでした。(てか、こんな話、初心者が最初からわかるわけがない)

たぶん困っているのはあなただけではありません。
きっと他の人も同じように困っているので、どんどん情報共有していきましょう。

RubyやRailsで新しく学んだことがあればQiitaへ、困って困ってどうしても先へ進まない場合はスタックオーバーフローへ書き込んでみてください。