2009-07-22 18 views
14

Dire che voglio memorizzare alcune variabili nel mio controller. Voglio inizializzarlo in un'unica azione, incrementarlo in un altro e leggerlo in un altro. La sola dichiarazione di questa variabile con @foo non funziona perché @foo muore dopo che l'azione che lo ha creato viene renderizzata.
Non voglio che questa variabile sia memorizzata in un modello.Come si memorizza una variabile di istanza su più azioni in un controller?

C'è un modo per conservare questa variabile oltre a memorizzarla in una sessione?
Sembra che mi sia imbattuto in questo semplice problema alcune volte e desidero conoscere il modo migliore per risolverlo.

risposta

22

Non proprio. Ogni chiamata a un'azione del controller è senza stato. Niente è disponibile al termine dell'azione del controller. Una nuova istanza controller viene creata per ogni richiesta e quindi scartata alla fine della richiesta.

Se non si desidera archiviarlo nella sessione o nel modello di database, non si dispone di molte opzioni se si desidera che tale variabile sia specifica per una determinata sessione.

Se è globale in tutte le sessioni, si potrebbe mettere in un @@class_variable piuttosto che un @instance_variable, ma che può ottenere disordinato una volta che si inizia ad avere più processi Rails (ciascuno che avranno la propria copia di esso), o se sei in esecuzione in modalità threadsafe, puoi finire con brutti bug di concorrenza.

Credo che si potrebbe guardare qualcosa come memcached, ma si sarebbe ancora bisogno di chiave che a qualche id_utente o altro marcatore di sessione (a meno che sia globale)

7

si potrebbe fare uso del costruito in Rails.cache meccanismo per memorizzare il valore ma, come menzionato nella prima risposta, dovresti metterlo in pratica come qualcosa di user_id. Questo è un buon modo di procedere poiché è possibile eseguirlo con diversi meccanismi di archiviazione.

Rails.cache.write(:foo) 
# in later action 
Rails.cache.read(:foo) 

Un altra cosa che si poteva guardare è l'hash flash, che fornisce un metodo mastio di rendere il valore del flash ultima più di una successiva richiesta.

Così in azione 1 è possibile creare il valore:

flash[:foo] = some_value 
flash.keep(:foo) 

In azione 2 è possibile accedere, e chiamare a mantenere ancora una volta, se si vuole rimanere in vita per le azioni più successive.

flash[:foo] #use it for something 
flash.keep(:foo) # keep it for another request 

È un po 'una cosa complicata da fare in modo pulito nel contesto delle richieste http.

+0

La cache è una buona idea, ma non penso che il metodo Flash funzionerà se si dispone di più server web. – Scott

+0

Dipende dalla memorizzazione della sessione perché l'hash flash è effettivamente memorizzato nella sessione - ad esempio se le sessioni sono disabilitate solo flash.now funzionerà – paulthenerd

+0

La cache è un'idea buona. Ma se sta usando il MemoryStore, è per memoria di processo, quindi a meno che tu non abbia un singolo processo che gestisce tutte le richieste, le richieste successive potrebbero non colpire il processo che lo ha in memoria. Se l'archivio di memoria è supportato da memcached, sarebbe molto meglio. –

1

Se si tratta di un conteggio o una stringa semplice, ritengo che la soluzione migliore sia memorizzarla nella sessione. In questo modo sarà lì se si utilizzano più server web.

Perché non si sta utilizzando una sessione per questo?

+0

Sono piuttosto nuovo di Rails, e ho appena pensato che la sessione fosse per * cose importanti * come un ID utente, non qualcosa di banale come un contatore. Grazie. –

11

Anch'io mi chiedo perché sei contrario all'uso della sessione? Se non ti piace lavorare con la sessione direttamente nelle tue azioni, potresti emulare una variabile di istanza @foo sopravvissuta con i filtri. Forse qualcosa del genere?

class FooController < ApplicationController 
    before_filter :load_foo 
    after_filter :save_foo 

    private 
    def load_foo 
     @foo = session[:foo] || 0 
    end 

    def save_foo 
     session[:foo] = @foo 
    end 

end 

Le vostre azioni avranno il in grado di manipolare il valore attraverso la variabile di istanza @count e questo sarà persistito automaticamente alla sessione.

1

Non preoccuparti, le sessioni non mordono.

Inoltre, la sessione è probabilmente il modo migliore per farlo.

Problemi correlati