我已经习惯了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'}] conditions = combine(array1,array2) items = Item.find(:all,:conditions =>条件)
这非常有效。但是我希望能够组合任意数量的数组,或者基本上是写作的简写:
conditions = combine(combine(array1,array2),array3)
任何人都可以帮忙吗?提前谢谢。
答案 0 :(得分:38)
您想要的是命名范围:
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方法。
答案 1 :(得分:7)
我不会像你提议的那样做。
由于find返回一个数组,您可以使用数组方法对其进行过滤,例如:
Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }...
您还可以使用命名范围获得所需内容。
答案 2 :(得分:1)
您可以查看Searchlogic。
它使得使用条件更容易
ActiveRecord
设置,甚至Arrays
。
希望它有所帮助。
答案 3 :(得分:1)
你可以(或者至少曾经能够)在Rails中进行过滤:
find(:all, :conditions => { :foo => 'foo', :bar => 'bar' })
其中:foo和:bar是活动记录中的字段名称。好像你需要做的就是传递一个哈希:field_name =&gt;价值对。