2009-07-17 16 views
6

No se puede entender esto. En el modelo de rieles, quiero llamar a un método dentro del mismo modelo para manipular los datos devueltos por un método de búsqueda. Se llamará a este método de 'filtro' desde muchos métodos de búsqueda personalizada dentro de este modelo, por lo que quiero que esté separado. (Y no realizar un filtrado del SQL es demasiado complicado)Rieles: método de llamada dentro del modelo

Aquí se muestra un ejemplo:

#controller 
@data = Model.find_current 

#model 
class Model 
    def self.find_current 
    @rows = find(:all) 
    filter_my_rows 
    return @rows 
    end 

    def filter_my_rows 
    #do stuff here on @rows 
    for row in @rows 
     #basically I remove rows that do not meet certain conditions 
    end 
    end 
end 

El resultado de esto es: método no definido `filter_my_rows'

Gracias por cualquier ayuda!

Respuesta

4

Parte del problema es que está definiendo un método de clase llamado find_current y un método de instancia llamado filter_my_rows. Generalmente los defines dentro del mismo alcance para que trabajen juntos.

Otra cosa es que puede hacer una gran cantidad del filtrado que necesita con una simple llamada de rechazo # Array. Por ejemplo:

@models = all.reject do |m| 
    # This block is used to remove entries that do not qualify 
    # by having this evaluate to true. 
    !m.current 
end 

Usted puede modularizar esto de alguna manera mediante la conexión de funciones según sea necesario, también, pero eso puede resultar tremendamente complicado de manejar si no tiene cuidado.

# Define reusable blocks that are organized into a Hash 
CONDITION_FILTERS = { 
    :current => lambda { |m| m.current } 
} 

# Array#select is the inverse of Array#reject 
@models = all.select(CONDITION_FILTERS[:current]) 

Mientras que usted indicó en su pregunta que esto sólo era necesaria debido a preocupaciones por no ser capaz de determinar la relevancia de un registro en particular antes de que todos los registros se cargan desde la base de datos, esto es generalmente una mala forma, ya que probablemente rechace una gran cantidad de datos que haya tenido problemas para recuperar e instanciar como modelos solo para descartarlos inmediatamente.

Si es posible, al menos debe almacenar en caché las filas recuperadas mientras dure la solicitud para que no tenga que seguir obteniéndolas una y otra vez.

+0

Esto funcionó para mí en parte. No entiendo completamente lambda, tendré que leer sobre él, pero el método de rechazo será muy útil para eliminar filas de la matriz de búsqueda. Gracias – mickey

2

utilizar un named_scope lugar

named_scope :current, :conditions => {:active => true} # this is normal find criteria 

entonces en su controlador

@date = Model.current 

también puede hacer las funciones lambda named_scopes

+1

Gracias, pero creo que no puedo usar el alcance ni ninguna condición de filtrado para el SQL porque las condiciones que necesito verificar provienen de datos de diferentes bases de datos (en diferentes servidores). Así que tengo que recorrerlos y verificarlos uno a uno a través de la asociación belongs_to. – mickey

0

¿Qué hay de malo en sus soluciones? ¿Qué estás buscando exactamente? Si entendí su punto de vista, el principal problema de su aplicación es que

This 'filter' method will be called from many custom find method within this model, so I want it to be separate.

... que no se puede utilizar named_scopes o with_scope, la primera solución que viene a la mente es la creación de una costumbre envoltura para actuar como un filtro.

class Model 
    def self.find_current 
    filtered do 
     all 
    end 
    end 

    def self.other_method 
    filtered do 
     all :conditions => { :foo => "bar" } 
    end 
    end 

    def self.filtered(&block) 
    records = yield 
    # do something with records 
    records 
    end 

end 
+0

Lo que está mal con mi método es que me da este error: método indefinido 'filter_my_rows '. Al igual que si no fuera capaz de descubrir que estoy tratando de llamar a un método desde dentro de sí mismo. Su método también me da el mismo error: método indefinido 'filtrado ' – mickey

+0

He solucionado el error. El método debe ser autofiltrado. –

3

función de clase y función de instancia es su problema.

No puede llamar a una función de instancia en su función de clase de esa manera.

Utilice self.filter_my_rows para definir su función (tenga en cuenta self) y todo saldrá bien.

Cuestiones relacionadas