2009-07-17 17 views
6

Impossibile capirlo. Nel modello di rotaie, voglio chiamare un metodo all'interno dello stesso modello per manipolare i dati restituiti da un metodo di ricerca. Questo metodo 'filtro' verrà chiamato da molti metodi di ricerca personalizzati all'interno di questo modello, quindi voglio che sia separato. (E non posso filtro dal SQL è troppo complicato)Rails: metodo di chiamata all'interno del modello

Ecco un esempio:

#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 

Il risultato di questo è: metodo non definito `filter_my_rows'

Grazie per tutto l'aiuto!

risposta

4

Parte del problema è che si sta definendo un metodo di classe chiamato find_current e un metodo di istanza chiamato filter_my_rows. In genere li definisci entrambi nello stesso ambito in cui possono lavorare insieme.

Un'altra cosa è che puoi fare molto del filtraggio di cui hai bisogno con una semplice chiamata # scarto array. Per esempio:

@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 

È possibile rendere modulare questo un po 'inserendo nelle funzioni, come richiesto, anche, ma che si può ottenere selvaggiamente complicato da gestire, se non stai attento.

# 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]) 

Mentre lei ha dichiarato nella sua interrogazione che questo è stato richiesto solo a causa delle preoccupazioni di non essere in grado di determinare la rilevanza di un particolare record prima tutti i record vengono caricati dal database, questo è generalmente cattiva forma dal momento che probabilmente rifiuterà una grande quantità di dati che hai passato attraverso il problema del recupero e dell'istanza come modelli solo per scartarli immediatamente.

Se possibile, è necessario archiviare almeno le righe recuperate per la durata della richiesta in modo da non dover continuare a recuperarle più e più volte.

+0

Questo ha funzionato per me in parte. Non capisco perfettamente lambda, dovrò leggere su di esso, ma il metodo di rifiuto sarà piuttosto utile per rimuovere le righe dall'array di ricerca. Grazie – mickey

2

utilizzare un named_scope invece

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

poi nel controller

@date = Model.current 

si può anche fare le funzioni lambda named_scopes

+1

Grazie, ma io (penso) non è possibile utilizzare l'ambito o qualsiasi filtro delle condizioni per SQL perché le condizioni che ho bisogno di verificare provengono da dati provenienti da diversi database (su server diversi). COSÌ devo fare un ciclo e controllarli uno a uno attraverso l'appartenenza all'associazione stessa. – mickey

0

Cosa c'è di sbagliato con le vostre soluzioni? Cosa stai cercando esattamente? Se ho capito il tuo punto di vista, il problema principale della vostra implementazione è che

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

... che non è possibile utilizzare named_scopes o with_scope, la prima soluzione che viene in mente è quello di creare un custom wrapper per fungere da 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

Quello che non va nel mio metodo è che mi dà questo errore: metodo non definito 'filter_my_rows '. Proprio come se non fosse in grado di capire che sto provando a chiamare un metodo da se stesso. Il tuo metodo mi dà lo stesso errore: metodo non definito 'filtrato ' – mickey

+0

Ho corretto l'errore. Il metodo dovrebbe essere auto filtrato. –

3

la funzione di classe e la funzione di istanza è il tuo problema.

Non è possibile chiamare una funzione di istanza nella funzione classe in questo modo.

Utilizzare self.filter_my_rows per definire la funzione (notare lo self) e tutto andrà a destra.

Problemi correlati