私はDjango=に慣れています。ここでは、クエリセットで複数のフィルターメソッドを実行できます(つまり、Item.all.filter(foo="bar").filter(something="else")
)。
ただし、これはRailsで行うのはそれほど簡単ではありません。 Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }])
は、これが機能しないことを意味する配列を返します。
Item.find(:all, :conditions => ["foo = :foo", { :foo = 'bar' }]).find(:all, :conditions => ["something = :something", { :something = 'else' }])
したがって、フィルターを「スタック」する最良の方法は、条件配列を変更してからクエリを実行することであると考えました。
だから私はこの機能を思いつきました:
def combine(array1,array2)
conditions = []
conditions[0] = (array1[0]+" AND "+array2[0]).to_s
conditions[1] = {}
conditions[1].merge!(array1[1])
conditions[1].merge!(array2[1])
return conditions
end
使用法:
array1 = ["foo =:foo"、{:foo = 'bar'}] array2 = ["something =:something"、{:something = 'else'}]条件= bind(array1、array2)items =アイテム。 find(:all、:conditions =>条件)
これはかなりうまくいきました。しかし、私は任意の数の配列を組み合わせることができるようにしたい、または基本的に書くための省略形です:
conditions = combine(combine(array1,array2),array3)
誰かがこれを手伝ってくれる?前もって感謝します。
あなたが欲しいものは名前付きスコープです:
class Item < ActiveRecord::Base
named_scope :by_author, lambda {|author| {:conditions => {:author_id => author.id}}}
named_scope :since, lambda {|timestamp| {:conditions => {:created_at => (timestamp .. Time.now.utc)}}}
named_scope :archived, :conditions => "archived_at IS NOT NULL"
named_scope :active, :conditions => {:archived_at => nil}
end
コントローラーでは、次のように使用します。
class ItemsController < ApplicationController
def index
@items = Item.by_author(current_user).since(2.weeks.ago)
@items = params[:archived] == "1" ? @items.archived : @items.active
end
end
返されたオブジェクトはプロキシであり、SQLクエリは、コレクションの実際の処理(たとえば、表示)を行うか、プロキシでEnumerableメソッドを呼び出すまで実行されません。
あなたが提案したように私はそれをしません。
Findは配列を返すため、配列メソッドを使用してそれをフィルタリングできます。次に例を示します。
Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }...
名前付きスコープで必要なものを実現することもできます。
Searchlogic をご覧ください。
これにより、ActiveRecord
セット、およびArrays
でも条件を使用しやすくなります。
それが役に立てば幸い。
Railsでは、次のようにフィルタリングできます(または、少なくとも使用できるようになります)。
find(:all, :conditions => { :foo => 'foo', :bar => 'bar' })
ここで、:fooと:barはアクティブレコードのフィールド名です。 :field_name =>値のペアのハッシュを渡すだけでよいようです。