2011-08-17 39 views
3

的Rails 2.3.5的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)

我要退后一步,在这一切的转换为命名范围工作,但我真的很想知道如何得到这个工作这种方式。

+0

恕我直言,我认为你的命名范围的想法,甚至将它们分离成单一的方法比动态创建一个搜索字符串更好。命名范围(或方法)使您的模型(和方法)调用更容易阅读,同时尝试混合查询会导致很多痛苦并引入大量可能的问题。让rails为你查询(除非你需要他们完全优化,我猜) – corroded

+0

@corroded - 我不理解如何动态地组合10-15个命名范围并生成单个查询。我想避免一次又一次地触及数据库的一组条件,并且我不知道在给定搜索中将指定多少条件。 – Nick

回答

3

轨道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 

老答案

猴补丁Array类。在config/initializers目录中创建一个名为monkey_patch.rb的文件。

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) 
+0

你是我的Stack Overflow英雄。深深感谢这个提示。 – Nick

+0

我不能相信猴子的道路是唯一的逻辑方法来做到这一点。 –