Rails の興味深い実装メモの続き。
ActiveRecord の主な仕事は、DB の読み書きとデータの Validation なわけですが、コールバックを利用すると、Validation の前後や DB 読み書きの前後の、任意のタイミングで好きな処理を割り込ませることができます。
例えば、 Rails本のサンプルでは、
def before_create self.hashed_password = User.hash_password(self.password) end
といった感じで、DBにユーザ情報をインサートする前にパスワードを SHA1 でハッシュしたり、
after_create do |order| logger.info "Order #{order.id} created" end
といった感じで、オーダー情報をDBに格納した後ログに記録する、といったことをモデルの中で実行できるようになっています。
モデルで Validation するのと同様、これもコントローラの処理の簡略化につながり、より見通しの良いコードが書けていい感じですね。
また、上記のようなロギング処理を、モデルにやらせるのは気持ち悪い、という場合には、オブザーバを使ってモデルから処理を追い出すことができます。こんな感じで。
class OrderObserver < ActiceRecord::Observer def after_save(an_order) an_order.logger.info("Order #{an_order.od} created") end end
クラス名を OrderObserver としておくと、勝手に Order というモデルクラスのオブザーバとなってくれます。
さらに、observe メソッドで監視対象のクラスを複数指定することもできます。
class AuditObserver < ActiveRecord::Observer observe Order, Payment, Refund def after_save(model) model.logger.info("#{model.class.name} #{model.id} created") end end
こんな感じで、複数のモデルクラスに共通する処理を、元のクラスをまったくいじることなく、ひとつのクラスに記述しておくことができます。アスペクト指向っぽいですね。
Catalyst でこれと同じようなことができるのかな、と調べてみたところ、Catalyst::Plugin::Observe なるものが。といっても、ActiveRecord::Observer はモデルに特化しているのに対し、Catalyst::Plugin::Observe はフレームワーク全体で働くオブザーバなので、用途が異なるようです。
特に端的に異なるのは、コールバックイベントの種類ですね。ActiveRecord::Observer は before_validation, after_create などの、Validation や DB読み書きの処理段階に応じたイベントですが、Catalyst::Plugin::Observe は dispatch, prepare_action など、フレームワークの処理段階に応じたイベントとなってます。
Sledge 次期バージョンでは、ActiveRecord の様な Validation、コールバック、オブザーバはぜひ欲しいですね。お前が実装しろ、というのであれば、喜んでコード書きます。(あ、言っちゃった…)