2010-02-03 5 views
3

je un chercheur personnalisé défini ci-dessous:Finder ActiveRecord personnalisé invoquant des étendues nommées?

class ContainerGateIn << ActiveRecord::Base 
    ... 
    def self.search(text) 
    result = if text 
     text.split(' ').inject(self) do |result, criteria| 
     case criteria 
      when /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/ 
      result.search_by_date(criteria.to_date) 
      else 
      result.search_by_text(criteria) 
     end 
     end 
    else 
     self 
    end 
    end 
    ... 
end 

Où search_by_date et search_by_text sont portées nommés, et désireux est un champ défini comme nom désireux de chargement:

named_scope :eager, :include => [{:container_inventory => {:container => [:size_type, :grade]}}, :company, :truck, :hauler] 

L'association est la configuration par un HMT (has_many: à travers):

class ContainerDepot << ActiveRecord::Base 
    has_many :container_inventories 
    has_many :container_gate_ins, :through => :container_inventories do 
end 

le problème est de savoir si le viseur est invoqué par l'association viennent y nicher ContainerDepot, échouer s avec un ActiveRecord :: Statement :: Invalid, indiquant que la table a été spécifiée plusieurs fois.

ContainerDepot.first.container_gate_ins.eager.search(text) 
=> ActiveRecord::StatementInvalid: PGError: ERROR: table name "container_inventories" specified more than once 

je pouvais corriger en copiant tout le viseur personnalisé comme une extension de l'association:

class ContainerDepot << ActiveRecord::Base 
    ... 
    has_many :container_gate_ins, :through => :container_inventories do 
    def search(text) 
     ... custom finder code from ContainerGateIn ... 
    end 
    end 
    ... 
end 

Il est très sec si et introduit une redondance très inutile et potentiellement problématique, car le viseur personnalisé sera doivent être changés de temps en temps pour accommoder une logique de recherche supplémentaire.

Des idées sur comment cela pourrait-il être mieux fait?

Répondre

0

Vous pouvez utiliser named_scope avec un lambda, vous permettant de passer des paramètres à la méthode de détermination de la portée:

named_scope :eager, lambda {|text| {:conditions=>{:name=>text}, :include => [{:container_inventory => {:container => [:size_type, :grade]}}, :company, :truck, :hauler]}} 

Cela devrait vous permettre d'inclure et de filtrer avec un seul champ nommé.

Questions connexes