ActiveRecord::Base#with_scopeとscoped_access
ARのfindをある条件で絞っておきたい場合。with_scopeが使える。
Rails2.1以降?にはnamed_scopeというのもあるらしいけど、今回はRails1.2で。
例えばARの論理削除プラグイン、acts_as_paranoidではdeleted_atに削除フラグを立てる。通常のfindでは削除フラグが立ってるレコードは読まないようにAliasされており、あえて削除レコードをfindしたいときはfind_with_deleted(=オリジナルのfind)を呼べばいい。など。
acts_as_paranoidのように、モデル側で常に条件を絞っておく場合、
たとえばsakuraカラムがNULLじゃないレコードしかfindしないようにするには、
縛りたいModelの中で、
class << self def find_with_sakura(*args) with_scope(:find=>{ :conditions=>["sakura is not null",]}) do find_without_sakura(*args) end end alias_method_chain :find, :sakura end
のようにfindをalias_method_chainしてすり替えておく。
Railsプロジェクト全体通して一定条件を付加したい場合はこの方法でよいのかな……?
(ただし、この方法ではfind_by_xxxには適用されない←普段使わないけども)
・動的にこの条件を変更したい場合はController側でやりたいっす。
scoped_accessというプラグインを使う。
インストール
$ script/plugin install http://wota.jp/svn/rails/plugins/branches/stable/scoped_access/
例:特定グループに所属しているユーザーは常に特定グループの中からしか検索できないし、特定グループに所属しているユーザーが書いたMemoしか読めない
class ApplicationController < ActionController::Base scoped_access User, :restricted_user, :only => :search scoped_access Memo, :restricted_memo private def restricted_user { :find => { :conditions => ["group_id = ?", session[:group_id]] } } end def restricted_memo users = User.find(:all, :conditions=>["group_id = ?", session[:group_id]] users_id_list = users.map(&:id) { :find => { :conditions => { :user_id => users_id_list } } } end end
ScopedAccess::MethodScoping.new()ってやらなくても、ハッシュを返せばイイみたい。
また、scoped_accessにBlockを渡したり、Hashを渡すなど書き方は色々あるようだ、詳しくは↓へ
参考:
基本的なwith_scopeの使い方
http://wota.jp/ac/?date=20060105
scoped_accessの使用例
http://wota.jp/ac/?date=20060816
ActiveRecord@ActionController で scoped_access をいろいろな書式で
http://d.hatena.ne.jp/MillyC/20080924/1222255886