Active Record 中的动态查找条件

5

我可以作为Rails中的索引操作,能够处理许多参数,例如:

params[:first_name] # can be nil or first_name
params[:age]        # can be nil or age 
params[:country]    # can be nil or country

当查找用户时,我希望同时满足不为空的所有条件。这样可以得到8种查找条件的排列组合。

如何保持我的代码DRY和灵活性,并且不用一堆if语句来构建查找条件。请注意,如果没有指定任何条件,则只需返回User.all

7个回答

3

可以参考以下翻译:

conditions = params.only(:first_name, :age, :country)
conditions = conditions.delete_if {|key, value| value.blank?}

if conditions.empty?
  User.all
else
  User.all(:conditions => conditions)
end

很奇怪,我的参数哈希似乎没有only方法。 - Sam Saffron

3

我通常会使用命名作用域来处理这种情况:

class User < ActiveRecord::Base
  named_scope :name_like, lambda {|name| {:conditions => ["first_name LIKE ?", "#{name}%"]}}
  named_scope :age, lambda {|age| {:conditions => {:age => age}}}
  named_scope :in_country, lambda {|country| {:conditions => {:country => country}}}
end

class UsersController < ActionController
  def index
    root = User
    root = root.name_like(params[:first_name]) unless params[:first_name].blank?
    root = root.age(params[:age]) unless params[:age].blank?
    root = root.country(params[:country]) unless params[:age].blank?

    @users = root.paginate(params[:page], :order => "first_name")
  end
end

这通常是我的做法。

1

这似乎运行得相当不错:

conditions = params.slice(:first_name, :age, :country)
hash = conditions.empty? ? {} : {:conditions => conditions}
@users = User.all hash 

1

使用James Healy的答案,我修改了代码以在Rails 3.2中使用(如果有人需要的话)。

conditions = params.slice(:first_name, :age, :country)
conditions = conditions.delete_if {|key, value| value.blank?}

@users = User.where(conditions)

0
如果你正在处理一个古老的项目(Rails 2.x)并且非常混乱,你可以尝试以下方法来添加新字段到原始查询中。
原始代码:
User.find(:all,
   :conditions => ['first_name LIKE ? AND age=? AND country=?',
        "#{name}%", age, country]

zip_code字段上添加一个新的动态条件:

zip_code  = params[:zip_code]   # Can be blank
zip_query = "AND zip_code = ?" unless zip_code.blank?

User.find(:all,
   :conditions => ['first_name LIKE ? AND age=? AND country=? #{zip_query}',
        "#{name}%", age, country, zip_code].reject(&:blank?)

conditions 数组中添加一个 reject(&:blank?) 将过滤掉 nil 值。

注意:如果你是从零开始编码或重构代码,其他答案会更好。


0
你可以尝试使用Ambition,或者其他一些ActiveRecord扩展。

0

这对我也有效

conditions = params[:search] ? params[:search].keep_if{|key, value| !value.blank?} : {}
User.all(:conditions => conditions)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接