例えば、フォームからの入力で
params # => {:city => "tokyo", :age => 30}のようなパラメータが与えられるとすると、 fat controller を気にしなければ rails のアクションの実装は以下のようにやってました。
def index
conds, args = [], {}
unless (city = params[:city]).blank?
conds << "city = :city"
args[:city] = city
end
unless (age = params[:age]).blank?
conds << "age = :age"
args[:age] = age
end
if conds.blank?
@users = User.find(:all)
else
@users = User.find(:all, :conditions => [conds.map{|c|"(#{c})"}.join(" AND "), args])
end
end
named scope を使うと
class User
named_scope :city, lambda{|city| {:conditions => ["city = ?", city]}}
named_scope :age, lambda{|age| {:conditions => ["age = ?", age]}}
end
def index
@users = [:city, :age].inject(User) do |ret, scope|
params[scope].blank? ? ret : ret.send(scope, params[scope])
end.all
end
すばらしいじゃないですか。
検索してみるとすでに同じ事を思いついている人はたくさんいるようですね。
(上記、実際に動かしたコードをブログ用に書き換えたのでどっか間違っていたらごめんなさい。)