2008-09-17 18 views
5

Tengo algunos modelos que necesitan condiciones de búsqueda personalizadas. Por ejemplo, si tengo un modelo de contacto, cada vez que se llama a Contact.find, quiero restringir los contactos devueltos que solo pertenecen a la cuenta en uso.Anulación de "buscar" en ActiveRecord el modo DRY

me encontré por Google (que He personalizado un poco):

def self.find(*args) 
    with_scope(:find => { :conditions => "account_id = #{$account.id}" }) do 
    super(*args) 
    end 
end 

Esto funciona muy bien, a excepción de unas pocas ocasiones en que account_id es ambiguo por lo que lo adaptaron a:

def self.find(*args) 
    with_scope(:find => { :conditions => "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do 
    super(*args) 
    end 
end 

Esto también funciona muy bien, sin embargo, quiero que sea SECO. Ahora tengo algunos modelos diferentes que quiero que se use este tipo de función. ¿Cuál es la mejor manera de hacer esto?

Cuando responda, incluya el código para ayudar a nuestras mentes a captar la metaprogramación Ruby-fu.

(estoy usando Rails 2.1)

Respuesta

8

usted no nos dice qué versión de rieles que está utilizando [editar - es sobre raíles 2.1 siguiendo así el consejo está en pleno funcionamiento], pero me recommand utiliza el siguiente formulario en lugar de sobrecargar encontrará:

account.contacts.find(...) 

este envolverá automáticamente el hallazgo en un ámbito en el que se incluye la cláusula de usuario (ya que usted tiene la account_id que se supone que tiene la cuenta en algún lugar cercano)

Le sugiero que compruebe lo siguiente recursos en los ámbitos

+0

Gracias Jean, que funcionará a tratar y es probablemente la manera correcta para hacerlo. La introducción de la cuenta es una nueva adición al código existente, así que supongo que estaba complicando las cosas desde esa perspectiva. Voy a revisar y modificar el código existente para que sea delimitado por la cuenta. –

0

para dar una respuesta específica a su problema, sugeriría mover el método mencionado anteriormente en una módulo para ser incluido por los modelos en cuestión; entonces usted tendría

class Contact 
    include NarrowFind 
    ... 
end 

PS. Tenga cuidado con el escape sql del account_id, probablemente debería usar la sintaxis :conditions=>[".... =?", $account_id].

+0

Probablemente sea una mala idea anular completamente el buscador básico de un modelo, ya que rompería las expectativas de cualquier persona externa al equipo, incluidos los autores de complementos (complemento de búsqueda de opinión) sin mencionar el riesgo de romper los rieles (poco probable pero imposible) – Jean

5

El consejo de Jean es bueno.Asumiendo que su modelos de aspecto:

class Contact < ActiveRecord::Base 
    belongs_to :account 
end 

class Account < ActiveRecord::Base 
    has_many :contacts 
end 

usted debe utilizar la asociación contacts de la cuenta corriente para asegurarse de que está consiguiendo solamente Contact registros de ámbito a esa cuenta, así:

@account.contacts 

Si desea agregar condiciones adicionales a su consulta de contactos, puede especificarlas usando find:

@account.contacts.find(:conditions => { :activated => true }) 

Y si se encuentra co nstantly consulta para los usuarios activados, puede refactorizar en un ámbito con nombre:

class Contact < ActiveRecord::Base 
    belongs_to :account 
    named_scope :activated, :conditions => { :activated => true } 
end 

Qué usted entonces utilizar como esto:

@account.contacts.activated 
Cuestiones relacionadas