HasFinderというRails pluginが激しく便利

nick – HasFinder — It’s Now Easier than ever to create complex, re-usable SQL queries

一言で説明すると「いろいろな条件のFindをモデルのメソッドにして便利に利用できる」というもの。

導入

とりあえずは入れて使う方法から。

$ sudo gem install has_finder

environment.rbに以下追記。

gem 'has_finder'
require 'has_finder'

使ってみる

早速メソッド作ってみる。

class Item < ActiveRecord::Base
  has_finder :stocked, :conditions => ["stock > 0"]
  has_finder :has_image, :conditions => {:has_image => true}
end

これだけなら別に普通にメソッド定義できるものをちょっと簡単に書けるようにしただけのことでフーンってかんじ。
だがこれらのメソッドをいろいろと組み合わせて柔軟に使っていけるところがHasFinderの真骨頂。

手始めとしてメソッドを連結して使ったりとか。

items = Item.stocked.has_image

絞り込み条件がいいかんじにDRYに。
この後にさらにfindで絞り込んだり並べ替えたりも可能。集計関数も行ける。

items = Item.stocked.has_image.find(:all, :conditions => ["maker_id = ?", params[:maker_id]], :order => 'price')
items = Item.stocked.has_image.count

関連といっしょに使っても問題なし。

class Category < ActiveRecord::Base
  has_many :items
end

class Item < ActiveRecord::Base
  has_one :category
  has_finder :stocked, :conditions => ["stock > 0"]
  has_finder :has_image, :conditions => {has_image => true}
end

category.items.stocked

ページネーションもおk。

items = Item.stocked.paginate(:page => params[:page], :conditions => ["category_id = ?", @category.id], :order => 'name', :per_page => 20)

メソッドに引数を取って条件の値の指定を動的に行うこともできる。

class Item < ActiveRecord::Base
  has_finder :price_under, lambda {|price| { :conditions => ["price < = ?" , price] } }
end

items = Item.price_under(10000)

ほかAssociation extentionsみたいなこともできる。

もうすぐ標準

RailsのEdgeでは本体に取り込まれている模様。

Ryan’s Scraps: What’s New in Edge Rails: Has Finder Functionality

has_finderではなくnamed_scopeで定義するようになってたり若干変わってるようだけど、もうすぐ標準で使えるようになるみたいですな。