AC::Resourceとfindのレシーバの話。
上記の続き。
findメソッドの中に必須のスコーピングをまとめられる、というところから、するとfindのレシーバ次第でコンテキストに沿ったスコープを生成できるのではないか、と考えました。ちょっとだけ北欧、でもないか。
resouceの話と絡めるとこんな感じに書けそう。
class EntriesController < ApplicationController # recognized as below # /entries/:id # /blogs/:blog_id/entries/:id def show context = params[:blog_id].blank? ? Entry : Blog.find(params[:blog_id]) @entry = context.find(params[:id]) respond_to{|format| format.html } end end
なるほどなるほど。contextをもうちょっと賢くすればより賢いかも。
module ContextDetector private def context key = @@finder_context.detect{|context_key| not params[context_key + "_id"].blank? } if key klass = key.capitalize.constantize return klass.find(params[key]) else # 要はコントローラ名から対応するモデルを取得してます return self.class.controller_name.singularize.capitalize.constantize end end end
で、mixin
class EntriesController < ApplicationController include ContextDetector @@finder_context == [:blog, :user].freeze # recognized as below # /blogs/:blog_id/entries/:id # /users/:user_id/entries/:id # /entries/:id def show @entry = context.find(params[:id]) respond_to{|format| format.html } end end
ほほう。けっこうすっきりします。
/users/:user_id/blogs/:blog_id/entries/:entry_idというときに、user_idとblog_idのどちらでも絞り込みたい、という場合なんかのためにcontext()をもうちょい賢くしなきゃいけませんね。
とはいえ、もうちょっと可能性を検討してみたい書き方です。