アラウンドエイリアスでbefore_destroyの挙動を変える
どうやらこのエントリは変態アドベントカレンダー in Summerの5日目のエントリのようです。
←前の日のエントリ | 次の日のエントリ→
実はワタクシ、このアドベントカレンダーは参加表明だけして、すっかり忘れてましたww 昨日の夜になって思い出したので、なにも仕込みがない状態で書いています。なので変態成分が薄めなのはマジカンベン。
でも変態分は他の人が補給してくれるから問題ないよね?(チラッチラッ
で本題。今回はなぜかRuby(というかRuby on Rails)の話。
ActiveRecordのbefore_destroyなどで処理をおこなうのは、サバンナ*1ではよくあったりする要求なのですが、これって大概同じような処理になることが多いです。でもコールバックの処理内容は自Modelにしか書けないので、複数Modelに似たような処理が記述されて非常にDRYじゃありません。
そんな時には、アラウンドエイリアスでこのような似通った処理をまとめてしまいましょう。
まずは、config/initializers辺りに以下のようにモジュールを定義します
module BeforeProcessExtension def before_process #1 define_method :destroy_with_something do #destroy前にやっておきたい処理を記述... self.destroy_without_something end alias_method :destroy_without_something, :destroy #2 alias_method :destroy, :destroy_with_something #3 end end ActiveRecord::Base.send :extend, AttachFileExtension
ちょっと解説。
- #1 ここでこのモジュールをModelに組み込むための入り口になるメソッドを定義します。Modelからはこれをコールしてやります。
- #2 ここが理解できれば、なんてことはない。alias_methodで本来のdestroyメソッドをdestroy_without_somethingという名前に変更してしまいます。
- #3 そしてここで、destroy_with_somethingをdestroyメソッドに名前を変えてしまいます。
こんな風にエイリアスを付け替えることで、本来のメソッドにはない処理をすることも可能です。
あとはModel側で
class Employee < ActiveRecord::Base ... before_process end
とか書いておけば、このEmployeeクラスのdestroyメソッドだけ、別の処理を行うことができます。
もしModel側から何かパラメータを渡したい場合は、モジュールのbefore_processを
def before_process(hoge) #引数hogeを使った処理 ... end
と定義して、Model側で
class Employee < ActiveRecord::Base ... before_process "fuga" end
このようにパラメータを渡してもおk
また、元のdestroyメソッドを呼びたい場合はdestroy_without_somethingメソッドを呼び出せばいいわけで、とっても楽ですね!
Rubyだとメソッドの名前も動的に変えられてしまうので、こんなことができちゃうんですねぇ・・・おそロシア
アラウンドエイリアスについては「メタプログラミングRuby」に詳しい*2ので、詳細はそちらで。
- 作者: Paolo Perrotta,角征典
- 出版社/メーカー: KADOKAWA/アスキー・メディアワークス
- 発売日: 2010/08/28
- メディア: 大型本
- 購入: 18人 クリック: 533回
- この商品を含むブログ (125件) を見る
さて、次は dproject21 さんのようですよ。どんなド変態ネタが飛び出すか、今から楽しみですね!