まずはネストという言葉に関する定義の問題ですが、 諸橋さんが書いているように 、PostsコントローラはComments コントローラを集約(aggregates)しますが、 内包(compose)する訳ではありません。

たとえば、管理画面に対応するAdminコントローラから、 Commentの削除や修正を行う場合に、AdminコントローラからCommentsコントローラを集約する事を考えると、その必要性が分かりやすいと思います。

PostsコントローラにCommentsを制御するコードを書いてしまう(内包してしまう)と、 Adminコントローラで同じ事をする必要が出来た場合に、 同じようなコードを書く必要が出てきます。

Don't Repeat Yourself!

結果として、メンテナンス性の悪いコードが出来上がります。 この事が、Postsコントローラの中でCommentsリソースを制御する コードを書く事の問題の本質だと思います。 もちろん、あらかじめCommentsを集約する存在が Postsしか無いと分かっている場合には問題ありません。

という事で、 続いて検索やCRUD以外の操作はどうするのかという問題について。

この問題を考えるための重要な視点として、最近のRailsやMerbでは、 リソースを制御するためのリソースコントローラと、 それ以外の制御をするための汎用コントローラの役割が分けて考えられるようになってきているという事があります。

上述の話の中で登場するコントローラを当てはめてみると、 以下のようになります。

コントローラの分類
リソースコントローラ汎用コントローラ
PostsAdmin
CommentsDashboard

リソースコントローラとは、特定のモデルに対してCRUD(create, read, update, delete)操作を行う事に特化したコントローラです。

そう考えると、検索やCRUD以外の操作は、 汎用コントローラが行うのが自然な気がします。 例えば、ブログの記事(Posts)やコメント(Comments) の検索を行う場合であれば、 SearchコントローラがPostsコントローラやCommentsコントローラ を集約すればOK. 疑似コード的に表現すると、以下のような感じになります。

   1  Search#posts with_scope(query){ Posts#index }
   2  Search#comments with_scope(query){ Comments#index }

この構造は2年ぐらい前にRailsで使ってみたのですが、 Railsのコントローラの実装がネストに向いていないので、 パフォーマンス上の問題に苦しみました。 Railsのコントローラは、フィルタの実行、アクションの実行だけでなく、レスポンスの作成を担っているので、ネストさせた場合に、 いったん作成したレスポンスを破棄する必要があるなど、無駄が大きいのです(Railsではお馴染みのDoubleRenderErrorが発生するのもこのせいです)

しかし今であれば、Merbを使う事によってこの問題は解決します。 Merbのコントローラはレスポンスの作成をする必要が無く、非常にシンプルなので、ネストさせてもパフォーマンスの問題はほとんどありません。

ということで、Merbを使えばみんなHappyになるよという話でした。

前回の記事の追補

前回の記事では、Aggregatorの#showで、POST, PUT, DELETEを Aggregatedに委譲するという話を書きましたが、 例えばPostsコントローラがCommentsとTrackbacksの 2つのリソースを集約している場合に、 どちらのリソースに対する操作なのかを判別する方法を用意する必要があるので、どうやって実現するか書いておきます。

   1  posts/1            -> Posts#show
   2  posts/1/comments   -> Posts#show -> Comments
   3  posts/1/trackbacks -> Posts#show -> Trackbacks

こんな感じに、posts/1/:resource に対するPOST, PUT, DELETEを、 :resourceに対応するリソースコントローラに委譲する感じですね。

posted by Png genki on Wed 21 Jan 2009 at 10:19
Contents
Answer to resource, the CRUD and everything
Comments
dsjf: https://gist.github.com/6bf1bf2c3cbb5eb6e7a7 これ... '13-1
瀧内元気: おお、チェックしてみます。thx! '11-12
overisland: Reeder for iPhone もこの UI を実装していますね。 '11-12
瀧内元気: その情報は見たのですが、以下のサイトによると、現在はまた必要になってるっぽいんですよね。 ... '11-12
tkawa: http://devcenter.heroku.com/articles/rails31_he... '11-12
Services from s21g
twpro(ツイプロ)
Twitterプロフィールを快適検索
地価2009
土地の値段を調べてみよう
MyRestaurant
自分だけのレストラン手帳
Formula
ブログに数式を埋め込める数式コミュニティ