こんにちは、鈴木です。
TECHSCORE Advent Calendar 2014、13 日目の記事です。
12/5 に Ruby on Rails 4.2 の RC2 が出ましたね!(すぐに rc3 が出ました!)
今年中に正式版が出るかは分かりませんが、そろそろ変更内容をキャッチアップしておきたいですね。ということで、今回は Rails 4.2 のハイライトをお送りします!
Active Job
今まで非同期処理といえば Resque や Delayed Job, Sidekiq のようなライブラリを使用してきました。Rails 4.2 では、それらのジョブ/キューの共通インタフェースとして ActiveJob が導入されました。
以下のように ActiveJob::Base を継承したクラスを作成することで、ジョブを定義します。(メソッドの引数は自由に決めることができます。ここでは user を渡しています。)
1 2 3 4 5 6 7 8 9 10 11 |
class HelloJob < ActiveJob::Base queue_as :default def perform(user) # ここに処理を記述する. # ユーザ登録から一定時間経過後に一時データを削除する. user.clear_temporary_data! end end |
ジョブのクラス app/jobs/ の中に作成します。以下のように「rails generate job <名前>」で生成することができます。
1 2 3 4 |
$ rails generate job hello invoke test_unit create test/jobs/hello_job_test.rb create app/jobs/hello_job.rb |
ジョブの呼び出しは次のように行います。
1 2 |
user = User.first! HelloJob.perform_later(user) |
ジョブの実行までしばらく時間を空けたい場合は、set メソッドでオプションを指定することができます。
1 2 |
user = User.first! HelloJob.set(wait: 30.minutes).perform_later(user) |
非同期処理のジョブにオブジェクトを渡せる・・・ように見える
ところで上記のコードですが、perform_later メソッドに ActiveRecord オブジェクトである user を渡しています。
普通に考えると、非同期実行されるジョブは別プロセスで動くため、オブジェクトをそのまま渡すことはできないはずです。
やり方としては、オブジェクトをシリアライズして渡すか、オブジェクトを参照する ID を渡すかのどちらかです。
ActiveJob では後者の方法、オブジェクトを参照する ID を渡す方法を採用しています。
Global ID
オブジェクトを参照する ID として、Global ID というものが導入されました。これはモデルを一意に識別する「gid://<アプリケーション名>/<モジュール名>::<モデルクラス名>/id」形式の値を生成します。
Global ID への変換と、モデルオブジェクトへの復元は自動的に行われるので意識しなくても使うことができますが、裏側でこのような変換が行われていることは頭の片隅に入れておきましょう。(モデルの属性を変更しても、それをデータベースに保存しなければジョブ側では変更前の値を参照することになります。)
ActiveJob がサポートするバックエンド
ActiveJob のドキュメントを見ると、以下のバックエンドに対応しているそうです。
意外と多くのジョブ/キューのライブラリがありますね。
- Backburner
- Delayed Job
- Qu
- Que
- queue_classic
- Resque 1.x
- Sidekiq
- Sneakers
- Sucker Punch
Asynchronous Mailers
Rails でメール送信するには ActionMailer を使用しますが、メール送信処理を非同期で行うことができるようになりました。非同期にするために、先ほど紹介した ActiveJob が使用されます。
以下のように deliver_later メソッドを使用すると、非同期でメールが送信されます。
1 2 |
# 非同期でメールを送る. HelloMailer.hello('こんにちは').deliver_later |
今までどおり、非同期にせずにメールを送りたい場合は deliver_now メソッドを使用します。
1 2 |
# 非同期にせずにメールを送る. HelloMailer.hello('こんにちは').deliver_now |
※今まで使用してきた deliver / deliver! メソッドは非推奨になりました。
Adequate Record
「Adequate」とは「適切な」や「十分な能力がある」といった意味の単語です。
Adequate Record は共通する SQL クエリをキャッシュすることで高速化を図ります。場合によっては 2 倍速くなることもあるそうです。
全てのクエリが速くなるわけではありませんが、特にアプリケーションのコードを修正することなく高速化されるのは嬉しいですね。
Web Console
デバッグ用の機能として、Web Console が導入されました。
どのようなものかは画面を見て頂いた方が早いと思いますので、以下のキャプチャをご覧ください。
エラー画面の下部の灰色の領域が Web Console です。irb のような REPL を提供してくれます。
View に「<%= console %>」と記述すれば通常の画面でも Web Console を使うことができるので、本番サーバでもアクセス制限をかけたページに Web Console を埋め込んでおけば、何かの役に立つかもしれません。Web Console に IP によるアクセス制限をかける場合は、次のように設定するだけで OK です。
1 |
config.web_console.whitelisted_ips = %w(127.0.0.1 192.168.0.0/24) |
マイグレーションで外部キーをサポート
マイグレーションで外部キーがサポートされました。今までは外部の gem に頼るか SQL を直接実行していましたが、Rails 4.2 では標準機能で外部キーを設定することができます。
外部キーを設定するには add_foreign_key メソッドを使用します。
1 2 3 4 5 6 7 8 9 10 |
#add_foreign_key from_table, to_table, options={} # articles.user_id -> users.id add_foreign_key :articles, :users # articles.owner_id -> users.id add_foreign_key :articles, :users, column: :owner_id # articles.user_login_id -> user.login_id add_foreign_key :articles, :users, column: :user_login_id, primary_key: :login_id |
外部キーを削除するには remove_foreign_key メソッドを使用します。
1 2 3 4 5 |
# remove_foreign_key from_table, options_or_to_table remove_foreign_key :articles, :users # または remove_foreign_key :articles, column: :user_id |
他にもいろいろ!
大きな変更点を見てきましたが、細かい修正も多くあります。非推奨だった機能が削除されたり、PostgreSQL9.4 の JSONB 型に対応したり色々ありますので、リリースノートをご一読することをお勧めします!
Enjoy Rails!