2010-12-18 12 views
23

खोज डेटाबेस पर एक खोज कैसे करेगी जब खोज आईडी, ज़िप, शहर और राज्य जैसे कई वैकल्पिक पैरामीटर प्रदान कर सकती है? ये या तो मूल्य हो सकते हैं या पूरी तरह खाली हो सकते हैं। मैं इस तरह की रेल क्वेरी कैसे बनाऊंगा?रेल वैकल्पिक पैरामीटर के साथ खोजें?

उत्तर

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 
    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 का उपयोग करता है के लिए:

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 कि केवल मौजूदा कार्यक्षेत्रों का उपयोग करता लिखें: : पैरामीटर, फिल्टर विधि के लिए वाक्य रचना है:

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

@ टोकलैंड मैंने आपके समाधान का उपयोग किया। यह http://railscasts.com/episodes/112-anonymous-scopes और http://railscasts.com/episodes/111- उन्नत-search-form से अधिक सुरुचिपूर्ण दिखता है। आपका बहुत बहुत धन्यवाद! –

+0

क्या इस समाधान में संभावित स्मृति रिसाव/डीओएस हमले की कमजोरता नहीं है? पूर्व, कोई बड़ी क्वेरी स्ट्रिंग में भेजता रहता है और मॉडल यादृच्छिक क्वेरी तारों को 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]) 
संबंधित मुद्दे