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()をもうちょい賢くしなきゃいけませんね。
とはいえ、もうちょっと可能性を検討してみたい書き方です。