2010-12-18 60 views
23

如果搜索可以提供很多可选参数,如ID,Zip,City和State,我将如何对数据库执行搜索?这些可以有值或完全空白。我将如何做这样的铁轨查询?Rails使用可选参数搜索?

回答

17

您可以建立一个查询:

conditions = {} 
conditions[:city] = city unless city.blank? 
conditions[:zip] = zip unless zip.blank? 
conditions[:state] = state unless state.blank? 
Address.find(:all, :conditions => conditions) 
+0

能否请你告诉我,如果我需要运行同一类型的查询在mongoid但比在参数的一个条件高,我该怎么能做到这一点?希望你能理解! – 2014-10-15 10:08:00

31

通常的建议是将逻辑模型,并保持控制器精简越好。有不同的方法用于过滤器的方法,所述第一个:

class Record < ActiveRecord::Base 
    def self.filter(attributes) 
    attributes.select { |k, v| v.present? }.reduce(all) do |scope, (key, value)| 
     case key.to_sym 
     when :id, :zip # direct search 
     scope.where(key => value) 
     when :city, :state # regexp search 
     scope.where(["#{key} ILIKE ?", "%#{value}%"]) 
     when :order # order=field-(ASC|DESC) 
     attribute, order = value.split("-") 
     scope.order("#{self.table_name}.#{attribute} #{order}") 
     else # unknown key (do nothing or raise error, as you prefer to) 
     scope 
     end 
    end 
    end 
end 

的第二种方法,写一个裸filter只使用现有的作用域:

class Record < ActiveRecord::Base 
    SUPPORTED_FILTERS = [:id, :city, ...] 
    scope :id, ->(value) { where(id: value) } 
    scope :city, ->(value) { where(city: "%#{value}%") } 
    ... 

    def self.filter(attributes) 
    attributes.slice(*SUPPORTED_FILTERS).reduce(all) do |scope, (key, value)| 
     value.present? ? scope.send(key, value) : scope 
    end 
    end 
end 

对于导轨5,它现在使用的ActionController: :参数,用于过滤方法的语法是:

def self.filter(attributes) 
    attributes.permit(SUPPORTED_FILTERS).to_hash.reduce(all) do |scope, (key, value)| 
    value.present? ? scope.send(key, value) : scope 
    end 
end 

模型可以从您的应用程序的任何地方调用,所以它们是可重复使用和易于测试。

class RecordsController < ApplicationController::Base 
    respond_to :html, :xml 

    def index 
    @records = Record.filter(params) 
    end 
end 
+1

+1好方法让控制器简单 – zetetic 2010-12-18 22:59:15

+1

@tokland我使用了你的解决方案。它看起来比http://railscasts.com/episodes/112-anonymous-scopes和http://railscasts.com/episodes/111-advanced-search-form更优雅。非常感谢! – 2012-08-28 11:30:24

+0

此解决方案是否存在潜在的内存泄漏/ DoS攻击漏洞?例如,有人持续发送大型查询字符串,模型保留key.to_sym'随机查询字符串? – 2014-11-15 06:03:25

0

http://metautonomo.us/projects/metasearch/是你所需要的:现在的控制器看起来那么简单。

= text_field_tag 'search[city_like]', '' 
= text_field_tag 'search[zip_equals]', '' 
= text_field_tag 'search[state_equals]', '' 

然后就是

Record.search(params[:search])