はじめに
Ruby 2.3のリリース前に、Ruby on Railsのバージョン5.0系列(以下Rails 5)の最初のベータ版がリリースされました。
Rails 5は、JSON APIサーバーやWebSocketサーバー用の新機能を導入するとともに、Ruby 2.2.2以上で動作するため内部的には大きな変更が加えられています。また、モデルがApplicationRecord
から継承されたり、Rakeタスクをrails
コマンドで実行できるようになったりといった基本的な部分にも大きく手を加えられています。
本記事では、GitHubのRailsプロジェクトのIssuesやPull Requestsの履歴をもとに、Rails 5の主要な新機能・変更点の紹介を行います。
※ 他のバージョンのRailsの主要な新機能・機能追加・変更点については以下を参照してください。
- ReactやwebpackもサポートしたRails 5.1の新機能・変更点 - Qiita
- Ruby on Rails 5.2の新機能(Active Storage, Content Security Policyなど) - Qiita
- Ruby on Rails 6の主要な新機能・機能追加・変更点
新機能
Rails API
ActionController::Base
の代わりにActionController::API
をコントローラで継承することによって、JSON APIサーバー用の軽量なRailsアプリケーションを構築することができるようになりました。
完全にAPIのみのRailsアプリケーションを作成する場合は、rails new
で--api
オプションを指定します。
$ rails new my_api --api
これによって、以下のことが行われます。
- APIサーバーを動かすのに最低限のミドルウェアがロードされます。
- アプリケーション内に生成される
ApplicationController
は、ActionController::API
を継承するようになります。 - ジェネレータでの、ビューやアセットの生成が行われません。
既存のRailsアプリケーションをAPIのみにする場合は、こちらを参考にしてください。
Rails API to Be Part of Rails 5
Action Cable
Action Cableを用いることで、リアルタイムな双方向通信を可能にするWebSocketの機能をRailsアプリケーションに簡単に追加することが可能になりました。Action Cableには、サーバーとクライアントの両方の機能が含まれています。
サーバー側では、ApplicationCable::Connection
やApplicationCable::Channel
などのクラスを用いて実装を行い、クライアント側では、CoffeeScript(JavaScript)のApp.cable.subscriptions.create
によってサーバー側のAppearanceChannel#subscribed
メソッドを呼び出します。
ジェネレータでサーバーとクライアントの両方のコードを生成することができます。以下はchat
というchannelを生成する例です。
$ rails generate channel chat
詳細なコード例についてはこちらを参考にしてください。
rakeタスクをrailsコマンドから実行できるように
rake
コマンドで実行する各種タスクがrails
コマンドでも実行できるようになりました。
たとえば、DBのマイグレーションはrails db:migrate
、ルーティングの確認はrails routes
で行えるようになっています。
Implement rake proxy for rails cli
Turbolinks 5
data-turbolinks-permanent
をDOM要素につけることでページ間で保持されるようになり、状態の初期化を必要としないので、より高速に動作するようになりました。
サイドバーなど、ページ間で固定の要素の場合は、data-turbolinks-permanent
を付与し、ページ間で保持しない要素は、data-turbolinks-temporary
をつけると良いようです。
<div id="nav" data-turbolinks-permanent></div>
<div id="footer" data-turbolinks-temporary></div>
Sprockets 3のサポート
Rails 4まではconfig/initializers/assets.rb
でどのアセットをプリコンパイルするか指定していましたが、Rails 5ではapp/assets/config/
ディレクトリ内のmanifest.js
で指定します。
アプリケーションの初期状態では、manifest.js
は以下のようになっています。
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
(以下の参考ページでは、Sprockets 4となっていますが、現在はまだSprockets 3です)
Rails 5: The Sprockets 4 Manifest
ActiveRecord::Attributes
モデルのattribute
で属性を指定することで、モデルの属性をSQLで取得したり、ActiveRecord::Relation
のwhere
メソッドに渡したりする方法をカスタマイズできるようになりました。たとえば、以下のようにDB上ではdecimal
型で定義された属性を
create_table :store_listings, force: true do |t|
t.decimal :price_in_cents
end
attribute
で、integer
を指定することで、整数に変換することができます。
class StoreListing < ActiveRecord::Base
attribute :price_in_cents, :integer
end
attribute
で変換を行う前後では以下のように異なります。
# before
store_listing.price_in_cents
=> BigDecimal.new(10.1)
# after
store_listing.price_in_cents
=> 10
詳細については以下のリファレンスを参照してください。
ActiveRecord::Attributes::ClassMethods
機能追加
クエリ関連のメソッド追加(#or
, #left_outer_joins
, #left_joins
)
ActiveRecord::Relation
にSQLでOR条件を指定できる#or
や外部結合を行う#left_outer_joins
のメソッドが追加されました。
Post.where('id = 1').or(Post.where('id = 2'))
=> SELECT * FROM posts WHERE (id = 1) OR (id = 2)
User.left_outer_joins(:posts)
=> SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
また、#left_outer_joins
のエイリアスの#left_joins
も追加されています。
Added #or to ActiveRecord::Relation
added ActiveRecord::Relation#outer_joins
Enumerable
モジュールに#pluck
と#without
が追加
特定のレコードのカラムを配列にする#pluck
メソッドと似た挙動のメソッドがハッシュの配列でも使えるようになりました。
[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
=> ["David", "Rafael", "Aaron"]
また、配列の中から特定の要素を除く#without
メソッドが追加されました。
people = ["David", "Rafael", "Aaron", "Todd"]
people.without "Aaron", "Todd"
=> ["David", "Rafael"]
Add Enumerable#pluck
Add Enumerable#without
ActiveRecord
の#save
にtouch
オプションが追加
レコードの保存時に#save
メソッドのオプションにtouch: false
を渡すことで、タイムスタンプを更新しないようにできるようになりました。
以下の例では、article
というモデルオブジェクトのデータを更新した後も、updated_at
の値は同じになります。
updated_at = article.updated_at
article.save!(touch: false)
article.update_at == updated_at
=> true
Provide :touch option to save() to accommodate saving without updating t...
ActiveRecord::Relation#in_batches
メソッドが追加
データ件数が大きなモデルに対して処理を行うActiveRecord#find_in_batches
がブロックに配列を渡してレコードを渡すのに対して、ActiveRecord#in_batches
メソッドは、ブロックにActiveRecord::Relation
を渡せるようになりました。オプションにof
を渡すことで、バッチのサイズを変更することができます。(デフォルトは1000)
Person.in_batches.each_record(&:party_all_night!)
Person.in_batches.update_all(awesome: true)
Person.in_batches.delete_all
Person.in_batches.each do |relation|
relation.delete_all
sleep 10 # Throttles the delete queries
end
変更点
belongs_to
の参照先がnil
の場合はバリデーションエラーに
Rails 4以前の挙動に戻すには、belongs_to
のオプションでoptional: true
を指定する必要があるそうです。
belongs_to should default to required: true
Active RecordのモデルがApplicationRecord
から継承されるように
Rails 5で新しくアプリケーションを作成した場合、app/models/application_record.rb
が以下のように作成され、他のモデルを生成する際も、ActiveRecord::Base
ではなく、ApplicationRecord
から継承を行うようになりました。
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
これまでは、アプリケーションのモデル全体にある機能を追加したい場合は、ActiveRecord::Base
にモンキーパッチを行うか、それぞれのモデルのクラスにモジュールをincludeする必要がありましたが、Rails 5以降では、ApplicationRecord
にメソッドなどを追加すればよいことになります。
Introduce ApplicationRecord, an Active Record layer supertype
Active JobのジョブもApplicationJob
から継承されるように
Active Jobに関しても同じく、各ジョブはActiveJob::Base
ではなく、以下のapp/jobs/application_job.rb
で記述される、ApplicationJob
から継承を行うようになりました。
class ApplicationJob < ActiveJob::Base
end
Add explicit base class for ActiveJob jobs
ActionController::Parameters
が、ハッシュから継承されなくなった
これまでのParameters
が、ActiveSupport::HashWithIndifferentAccess
から継承されていてEnumerable
モジュールの各メソッドで許可されていないパラメータを操作される危険性があったので変更したとのことです。(既存のハッシュなどのメソッドを使用している場合は、アップグレードの際に注意が必要です。)
Make AC::Parameters not inherited from Hash
alias_method_chain
が非推奨に
Rails 5では、Ruby 2.2.2以上を使用するので、ActiveSupport
のalias_method_chain
ではなくRubyのModule#prepend
を使用するようになっています。
Rails 5, Module#prepend, and the End of alias_method_chain
まとめ
Rails 5は、Rails APIやAction Cableなどこれまで以上にアプリケーションの幅を広げ、各種クエリ関連のメソッドなどが追加されたのでかゆい部分に手がとどくバージョンとなっているようです。すでにベータ版がリリースされているので、新機能を試したり、既存のRails 4アプリケーションのアップグレードを行ってみたりしてはいかがでしょうか。
参考サイト
rails/rails
Rails 5.0.0.beta1: Action Cable, API mode, Rails command
This week in Rails: Rails 5 - The Beta Awakens