2. 全体的な変更点
2013/10/03 シナジーマーケティング(株) 鈴木 圭
[Rails 4.0] 第2章 全体的な変更点
- 2.1. プラグイン (vendor/plugins) の廃止
- 2.2. script/rails が bin/rails に変更
- 2.3. テストディレクトリの変更
- 2.4. concerns ディレクトリの導入
- 2.5. index.html の動的生成
- 2.6. NotFound ページの改善
- 2.7. 開発用情報ページの導入
- 2.8. Inflection (単数形/複数形変換) の国際化
- 2.9. Object の try と try!
- 2.10. テストに関する変更
- 2.10.1. assert_blank, assert_present は非推奨
- 2.10.2. ActiveSupport::TestCase#pending が非推奨
- 2.10.3. テストログに実行中のテストクラスとメソッドが出力される
- 2.11. 内部的な改善
- 2.12. まとめ
2.1. プラグイン (vendor/plugins) の廃止
Rails4.0 ではプラグインの仕組みが廃止されました。
今まで(特に Rails2)までは vendor/plugins にライブラリを置くことが出来ましたが、この方法には以下の問題がありました。
- インストールしたプラグインのバージョンが管理しづらい。
- プラグイン間の依存関係の管理が手作業。
Rails3 ではプラグインの仕組みは残されたまま、bundler で依存ライブラリを管理する方法が取り入れられました。そして、Rails4.0 からは依存ライブラリの管理は bundler で行うことに一本化されました。
2.2. script/rails が bin/rails に変更
Rails3 では実行スクリプトは script/ ディレクトリに置かれていましたが、Rails4.0 からは bin/ ディレクトリ以下に実行スクリプトが置かれるように変更されました。
2.3. テストディレクトリの変更
Rails4 ではテストコードを保存するディレクトリが以下のように変更されました。
Rails3 時代はテストの種類ごとにディレクトリ分けされていましたが、Rails4.0 では unit や functional ディレクトリが無くなり、代わりに app/ ディレクトリ以下と同じ models, mailers, helpers, controllers ディレクトリに分けられました。これによって、テストコードを置く場所が以前より明確になりました。
test/performance ディレクトリが無くなっていますが、これはパフォーマンステストが外部ライブラリ rails-perftest に切り出されましたためです。
2.4. concerns ディレクトリの導入
Rails4.0 では Mixin 用モジュールを置くために、以下のディレクトリが準備されました。
- app/models/concerns
- app/controllers/concerns
それぞれモデルとコントローラのための Mixin 用モジュールを配置するディレクトリです。
Rails のディレクトリ構成を簡単におさらいすると、モデル、ビュー、コントローラ、ヘルパーは app ディレクトリ、どれにも属さないコードは lib ディレクトリに置く、とされていました。しかし、「いくつかのモデルで共通する機能」や「いくつかのコントローラで共通する機能」をどこに置くか明確には決められていませんでした。そのため、プロジェクトごとに独自の置き場所を決めるか、もしくは同じ内容のコードが共通化されること無く、複数の場所に存在することもありました。
Rails4.0 では共通機能はモジュールに分割し、concerns ディレクトリに配置します。
例として以下のコードをご覧ください。
# app/models/article.rb class Article < ActiveRecord::Base # … タグ付けに関するコード # … レーティングに関するコード # … その他のコード end
Article というモデルの中に、タグ付けに関するコードやレーティングに関するコードなど、色々な機能を実現するためのコードが含まれています。
このような場合、次のように「タグ付けに関するコード」や「レーティングに関するコード」は一つのモジュールに切り出して、app/models/concerns/ にファイルを置くと良いでしょう。
# app/models/article.rb class Article < ActiveRecord::Base include Tagging include Rating end # app/models/concerns/tagging.rb module Tagging extend ActiveSupport::Concern included do # … タグ付けに関するコード end end # app/models/concerns/rating.rb module Rating extend ActiveSupport::Concern included do # … レーティングに関するコード end end
注意点としては、分割したモジュール(concerns ディレクトリに置くモジュール)で scope や validates メソッドなどの ActiveRecord::Base の機能を使用することが多いと思います。そのような場合は、上記コードのように ActiveSupport::Concern を使用すると良いでしょう。もし以下のように書いてしまうと、NoMethodError となってしまいます。
# app/models/concerns/tagging.rb module Tagging # ここは ActiveRecord::Base ではないので validates メソッドは使えない. validates :tags, ... end
2.5. index.html の動的生成
Rails4.0 では public/index.html が無くなり、Railties に含まれる Rails::WelcomeController によって動的に生成されるようになりました。
小さな変更ですが、プロジェクト生成後に public/index.html を削除する手間が不要となりました。特に外向けに API を提供するだけのプロジェクトの場合はトップページを作成しない場合も多く、public/index.html を消し忘れていたためにブラウザでアクセスするとデフォルトの index.html が見えてしまったという事故も起こらなくなりました。
2.6. NotFound ページの改善
Rails4.0 では NotFound ページにルーティングの情報が表示されるようになりました。
開発中はリンク先の間違いなどで NotFound ページを見る機会が多いと思いますが、その場でルーティングのインクリメンタル検索を行うことができるので非常に便利です。
2.7. 開発用情報ページの導入
開発モードでは /rails/info/routes 及び /rails/info/properties でルーティングやアプリケーションの情報を確認することができるようになりました。NotFound ページと同様、ルーティングはインクリメンタル検索することができます。
これらのページに含まれる情報は「rake routes」や「rake middleware」でも確認することができますが、rake タスクはコマンドを打つたびに Rails の読み込みなどが行われるため若干スピードが遅いです。開発用情報ページは既に Rails が読み込まれた状態なので、そのような待ち時間はありません。
/rails/info/routes
/rails/info/properties
2.8. Inflection (単数形/複数形変換) の国際化
Rails では pluralize, singularize で単語の単数形/複数形を変換することができますが、Rails4 ではロケールを指定可能になりました。
日本語に対応させるには、config/initializers/inflections.rb に設定を追加する必要があります。
ActiveSupport::Inflector.inflections(:ja) do |inflect| inflect.plural /^(.+)$/, '\1々' inflect.singular /^(.+)々$/, '\1' inflect.irregular '札', '札束' inflect.irregular 'ドリフ', 'ドリフターズ' end
こうすることで、日本語に対しても pluralize や singularize で単数形/複数形を変換できるようになります。
# 単数形から複数形に変換. '人'.pluralize(:ja) # => "人々" '神'.pluralize(:ja) # => "神々" '村'.pluralize(:ja) # => "村々" '札'.pluralize(:ja) # => "札束" 'ドリフ'.pluralize(:ja) # => "ドリフターズ" # 複数形から単数形に変換. '人々'.singularize(:ja) # => "人" '神々'.singularize(:ja) # => "神" '村々'.singularize(:ja) # => "村" '札束'.singularize(:ja) # => "札" 'ドリフターズ'.singularize(:ja) # => "ドリフ"
2.9. Object の try と try!
Rails4.0 では Object#try の動作が変更されました。
以前の Object#try はメソッドが存在しない場合は NoMethodError が raise されていましたが、nil が返されるように変更されました。そして、今までどおり NoMethodError を raise する Object#try! メソッドが新しく導入されました。
2.10. テストに関する変更
2.10.1. assert_blank, assert_present は非推奨
assert_blank と assert_present は非推奨となりました。それぞれ次のように書き換えます。
assert_blank object → assert object.blank? assert_present object → assert object.present?
2.10.2. ActiveSupport::TestCase#pending が非推奨
ActiveSupport::TestCase#pending が非推奨になりました。今後は skip メソッドを使用します。
# Rails3 test 'sample' do pending ... end # Rails4.0 test 'sample' do skip ... end
2.10.3. テストログに実行中のテストクラスとメソッドが出力される
Rails4.0 ではテストを実行したときのログ (log/test.log) に実行中のテストクラスとメソッドが出力されるようになりました。
Rails3 では実行された SQL などしか出力されていませんでしたが、テストクラスとメソッド名も出力されるようになったため、ログを確認するときに便利です。
... (0.1ms) BEGIN Fixture Delete (0.3ms) DELETE FROM "users" Fixture Insert (0.4ms) INSERT INTO "users" ("name", "email", "id") VALUES ('MyString', 'MyString', 980190962) Fixture Insert (0.2ms) INSERT INTO "users" ("name", "email", "id") VALUES ('MyString', 'MyString', 298486374) (11.1ms) COMMIT (0.2ms) ALTER TABLE "articles" ENABLE TRIGGER ALL;ALTER TABLE "users" ENABLE TRIGGER ALL;ALTER TABLE "schema_migrations" ENABLE TRIGGER ALL (0.1ms) BEGIN ------------------------ UserTest: test_the_truth ------------------------ (0.1ms) ROLLBACK
2.11. 内部的な改善
Rails4.0 では表面的には見えづらいですが、内部的な改善も数多く行われています。
- デフォルトでスレッドセーフ
- config.threadsafe! は廃止
- ルーティングのパフォーマンス改善
- 内部エンジンがRack::MountからJourneyに変更
- sprocketsのバージョンアップが容易になった
- sprocketsと疎結合になったため
- ActiveSupport::Cache::MemCacheStore
- 依存ライブラリがmemcache-clientからdalliに変更
- ActiveSupport::Cache::Entry の最適化
- メモリ使用量と処理のオーバーヘッドを削減
気になるところではデフォルトでスレッドセーフになったことでしょうか。今まではマルチプロセス方式のアプリケーションサーバを使用することが多かったと思いますが、マルチプロセス方式ではメモリ消費量の観点で不利でした。Rails 自体がデフォルトでマルチスレッド対応となったことで、今後は Puma のようなマルチスレッド方式のアプリケーションサーバの導入を検討しやすくなります。
2.12. まとめ
全体的な変更点を見てきましたが、大小さまざまな改善が行われていることが分かりました。
次回は Model に関する変更点を解説します。