昨日の千駄ヶ谷.rbで7 Patterns to Refactor Fat ActiveRecord Modelsという記事をみんなで読んでいたのですが、その中の最後にあった Extract Decorators が使いドコロがわからないねってなっていたので、その記事にあるコードを手元で改良してわかりやすくしてみました。
元々のサンプルでちょっと変なのは、Facebookに投稿するものしか無いという点です。
このため、afterでやればいいのではっていう意見が出ていたんだけど、その場合だと例えばFacebookとTwitterに同時に投稿するとか、片方に投稿するとかってどうするのっていう話が出てくる。
というわけで、その点をわかりやすくするために改良をしてみました。ちなみに、ActiveRecordを利用せず、単なるRubyのコードです。
実行のところを見て貰えるとわかるんですが、単純に実行した場合はmodelをsaveしかしないことになります。
引数でFacebookだったりTwitterだったりGoogle Plusだったりに投げるみたいなのを追加で選べるようにしていて、FacebookとTwitterに同時に投稿するといったはてなブログでやってるような処理も簡単に書けるようになります。
実行例はこんな感じ。
[/Users/btm/tmp/gist/5567966] % ruby1.9 extradeco.rb --title 10 --user U "save to comment model, title: 10, author: U" "Your comment was posted." [/Users/btm/tmp/gist/5567966] % ruby1.9 extradeco.rb --title 10 --user U --fb "save to comment model, title: 10, author: U" "post to facebook, title: 10, user: U" "Your comment was posted." [/Users/btm/tmp/gist/5567966] % ruby1.9 extradeco.rb --title 10 --user U --fb --tw "save to comment model, title: 10, author: U" "post to facebook, title: 10, user: U" "post to twitter, title: 10, user: U" "Your comment was posted." [/Users/btm/tmp/gist/5567966] % ruby1.9 extradeco.rb --title 10 --user U --fb --tw --pl "save to comment model, title: 10, author: U" "post to facebook, title: 10, user: U" "post to twitter, title: 10, user: U" "post to plus, title: 10" "Your comment was posted."
このように後付の処理みたいなのを追加していくのにはすごく便利です。
もちろん、modelのsaveのあとにPostに失敗したときにどうするの?などは別途対応が必要になりますが、そこはこの話の本質ではないですね。
あと、この実装をする上ですごく使えるって感じたのがSimpleDelegatorです。
initializeの引数に来たものを自動的に叩いてくれるため、 @comment.title をどんどんたどっていってくれます。
Rubyの便利さにはまじで驚かされますねー。