Rails 2.3.5问题构建条件使用in(?)时动态变化

时间:2011-08-17 18:39:39

标签: ruby-on-rails activerecord conditional-statements

Rails 2.3.5

我已经查看了一些与动态建立条件有关的ActiveRecord查找的其他问题。

我知道有很多很棒的宝石,比如搜索逻辑,这在Rails3中更好。但是,我正在使用geokit进行地理搜索,我正在尝试构建一个标准条件集,这将允许我组合一系列不同的过滤器。

我有12个不同的过滤器,我正在尝试动态组合以进行高级搜索。我需要能够在(?)和IS NULL条件中混合使用等于,大于,小于等等。

以下是我正在努力工作的一个例子:

conditions = []
conditions << ["sites.site_type in (?)", params[:site_categories]] if params[:site_categories]
conditions << [<< ["sites.operational_status = ?", 'operational'] if params[:oponly] == 1
condition_set = [conditions.map{|c| c[0] }.join(" AND "), *conditions.map{|c| c[1..-1] }.flatten]


@sites = Site.find :all,
                     :origin => [lat,lng],
                     :units => distance_unit,
                     :limit => limit,
                     :within => range,
                     :include => [:chargers, :site_reports, :networks],
                     :conditions => condition_set,
                     :order => 'distance asc'

当条件表达式只有单个变量时,我似乎能够正常工作但是当我有一个(?)并且有一个值数组时,我得到一个错误的数字错误束缚条件。我加入和平整条件的方式(根据Combine arrays of conditions in Rails的答案)似乎没有正确处理数组,我不理解扁平化逻辑足以追踪问题。

所以,假设我在params中有3个值[:site_categories]我将上面的代码留给我以下内容:

条件是

[["sites.operational_status = ?", "operational"], ["sites.site_type in (?)", ["shopping", "food", "lodging"]]]

扁平的尝试是:

["sites.operational_status = ? AND sites.site_type in (?)", ["operational"], [["shopping", "food", "lodging"]]]

这给了我:

  

错误的绑定变量数(4为2)

我要退后一步,将所有这些转换为命名范围,但我真的很想了解如何以这种方式工作。

1 个答案:

答案 0 :(得分:3)

Rails 4

users  = User.all
users  = User.where(id: params[id]) if params[id].present?
users  = User.where(state: states) if states.present?
users.each do |u|
  puts u.name
end

旧答案

Monkey补充Array类。在monkey_patch.rb目录中创建名为config/initializers的文件。

class Array
  def where(*args)
    sql = args.first    
    unless (sql.is_a?(String) and sql.present?)
      return self
    end    
    self[0] = self.first.present? ? " #{self.first} AND #{sql}  " : sql 
    self.concat(args[1..-1])    
  end
end

现在你可以这样做:

cond = []
cond.where("id = ?", params[id]) if params[id].present?
cond.where("state IN (?)", states) unless states.empty?
User.all(:conditions => cond)