2011-08-27 16 views
15

con Rails 3, Come si può impostare una variabile di sessione in un modelloL'impostazione di una variabile di sessione in un modello di

session[:cannot_reason] = "no such item" 

mi piacerebbe impostare il sopra nel mio modello di utente. In questo momento ho ricevuto questo errore:

undefined local variable or method `session' for #<User:0x00000102eb9c38> 

Idee? Grazie

risposta

30

C'è un po 'inutile carico-culting per quanto riguarda se o meno modelli devono avere accesso ai dati di sessione. Penso che questo sia sciocco, dal momento che la sessione è in realtà solo un'altra forma di archiviazione persistente (anche se per un intervallo di tempo molto più breve) e, in Rails, sembra ok avere il tuo oggetto dominio anche in grado di persistere.

Detto questo, il modo non molto pulito per farlo sarebbe quello di passare l'hash della sessione come parametro nel metodo utente che opererà su di esso:

class User < ... 
    def mymethod(session, count) 
    session[:count] = count 
    end 
end 

Nel vostro controller, si sarebbe poi fare qualcosa di simile:

def update 
    # ... 
    user.mymethod(session, count) 
end 

Immaginando che mymethod sta attuando una logica di business, questo modificherà la session hash in modo appropriato. Non è necessario passare l'hash session indietro al controller perché Ruby passa i riferimenti agli oggetti (come un hash) - le modifiche vengono apportate in modo distruttivo a tali oggetti di riferimento.

Una parola di consulenza: l'esempio precedente, a mio parere, è maleodorante. Questo perché User è un modello ActiveRecord che (presumo) persiste in un database e stiamo aggiungendo un comportamento che lo rende persistente anche per un cookie di sessione. Per me, questo viola l'SRP e dovrebbe essere evitato.

Il modo in cui implementare questo sarebbe estrarre la logica di archiviazione di sessione in un oggetto di dominio separato che incapsula la ragione della sua esistenza. Forse, ad esempio, count non è solo un "conteggio", è il totale del numero di elementi nel carrello temporaneo dell'utente.

class TemporaryCart 
    def initialize(session) 
    @session = session 
    end 

    def add_item 
    # ... other item adding logic 
    @session[:temporary_cart][:num_items] += 1 
    end 
end 

Ora il controller sarebbe simile a questa:

def update 
    # ... 
    TemporaryCart.new(session).add_item 
end 

Questo è molto più rivelatrice e apre la porta per un modo ovvio per il codice di accesso della sessione astratto se vi trovate con memorizzazione delle sessioni molto . Notare anche che ho assegnato un nome ai dati nell'hash della sessione (ma non ho mostrato questa implementazione). Ti consiglio di farlo, in modo da non calpestare i piedi quando aggiungi altri dati.

7

In breve, non è possibile. In base alla progettazione, i modelli non hanno accesso ai cookie e alla sessione. Se per accedere agli elementi nella sessione dal modello, è necessario passarli esplicitamente dal controller.

+2

Come li passeresti? Modifica mentale con un esempio? Grazie al modello – AnApprentice

+4

non dovrei usare Session, questo è sbagliato su così tanti livelli –

5

L'oggetto di sessione non è visibile nei modelli. Passa come parametro a un metodo nel tuo modello (IMHO non valido) o definisci un metodo nel tuo modello che restituisce ciò che desideri e quindi memorizzalo nella sessione (dal controller).

class User < ... 
    def item_status 
    return :no_such_item 
    end 
end 

Nel vostro controller

session[:item_status] = current_user.item_status 
Problemi correlati