2010-12-18 4 views
23

ID、郵便番号、市区町村、州などの多くのオプションのパラメータを検索で提供できる場合、データベースの検索はどのように行いますか?これらは値を持つことも、完全に空白にすることもできます。私はどのようにしてレールのクエリを作成しますか?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ではなく、条件よりも大きいと、クエリの同じ種類を実行する必要がある場合、あなたはどのように私はそれを行うことができ、私に教えてくださいすることができ?あなたが理解することを願って! –

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 

第2の方法は、唯一の既存のスコープを使用すること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 

今ActionControllerを使用してレール5の場合: :パラメータは、フィルタメソッドの構文は次のとおりです。

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

+1

@tokland私はあなたのソリューションを使いました。 http://railscasts.com/episodes/112-anonymous-scopesとhttp://railscasts.com/episodes/111-advanced-search-formよりも洗練されています。どうもありがとう! –

+0

このソリューションには潜在的なメモリリーク/ DoS攻撃の脆弱性はありませんか? Ex、誰かが大量のクエリ文字列を送信し続けると、モデルはランダムなクエリ文字列をkey.to_sym'ingします。 –

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]) 
関連する問題