在rails中过滤ActiveRecord查询

use*_*154 24 ruby activerecord ruby-on-rails

我已经习惯了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
Run Code Online (Sandbox Code Playgroud)

用法:

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)
Run Code Online (Sandbox Code Playgroud)

有人能帮忙吗?提前致谢.

Fra*_*eil 39

您想要的是命名范围:

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
Run Code Online (Sandbox Code Playgroud)

在您的控制器中,使用如下:

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
Run Code Online (Sandbox Code Playgroud)

返回的对象是一个代理,并且在您真正开始对集合执行某些操作之前不会运行SQL查询,例如迭代(用于显示)或在代理上调用Enumerable方法.

  • named_scope现在在Rails 4中称为范围 (6认同)
  • 只是一个更新:现在在 Rails 4 中,您可以链接 where() 方法! (2认同)

kle*_*lew 7

我不会像你提议的那样做.

由于find返回一个数组,您可以使用数组方法对其进行过滤,例如:

Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }...
Run Code Online (Sandbox Code Playgroud)

您还可以使用命名范围获得所需内容.

  • 不对.您可以动态执行匿名范围:http://railscasts.com/episodes/112-anonymous-scopes (2认同)