Memorizzazione di oggetti in una sessione in Rails

Mi è sempre stato insegnato che immagazzinare oggetti in una sessione era una ctriggers idea. Invece gli ID dovrebbero essere archiviati che recuperano il record quando necessario.

Tuttavia, ho un’applicazione che mi chiedo è un’eccezione a questa regola. Sto costruendo un’applicazione flashcard e le parole interrogate si trovano in una tabella nel database il cui schema non cambia. Voglio memorizzare le parole che vengono attualmente interrogate in una sessione, in modo che un utente possa terminare la propria posizione nel caso in cui si spostino su una pagina separata.

In questo caso, è ansible fare a meno di memorizzare queste parole come oggetti nel database? Se è così, perché? Il motivo per cui lo chiedo è perché il quiz è progettato per spostarsi rapidamente, e odio sprecare una chiamata al database sul recupero di un record che non cambia mai in primo luogo. Tuttavia, forse non ci sono altri aspetti negativi di una sessione di grandi dimensioni di cui non sono a conoscenza.

* Per la cronaca, ho provato a memorizzarlo nella cache con i metodi memcache incorporati in Rails 2.3, ma apparentemente ha una dimensione massima per articolo di 1 MB.

La ragione principale per cui non si memorizzano oggetti nella sessione è che se la struttura dell’object cambia, si otterrà un’eccezione. Considera quanto segue:

class Foo attr_accessor :bar end class Bar end foo = Foo.new foo.bar = Bar.new put_in_session(foo) 

Quindi, in una versione successiva del progetto, si modifica il nome della barra. Riavvia il server e prova ad afferrare foo dalla sessione. Quando tenta di deserializzare, non riesce a trovare Bar ed esplode.

Potrebbe sembrare che sarebbe facile evitare questo trabocchetto, ma in pratica, l’ho visto mordere un numero di persone. Questo perché la serializzazione di un object a volte può richiedere più di quanto sia immediatamente evidente (questo tipo di cose dovrebbero essere trasparenti) e, a meno che non si abbiano regole rigorose su questo, le cose tenderanno ad essere sconcertate.

Il motivo per cui normalmente è disapprovato è che è estremamente comune per questo mordere le persone in ActiveRecord, dato che è abbastanza comune che la struttura della tua app cambi nel tempo e che le sessioni possano essere deserializzate una settimana o più dopo la loro creazione.

Se capisci tutto questo e sei disposto a mettere l’energia per essere sicuro che il tuo modello non cambi e non stia serializzando nulla in più, probabilmente stai bene. Ma fa attenzione 🙂

Rails tende a incoraggiare il design RESTful e l’uso delle sessioni non è molto riposante. Probabilmente creerò una risorsa Quiz con un sacco di parole e una current_word. In questo modo, quando torneranno, saprai dove si trovavano.

Ora, REST non è tutto (dipende da chi si parla), ma c’è un caso piuttosto buono contro le sessioni di grandi dimensioni. Ricorda che le sessioni scrivono cose da e verso il disco, e più dati stai scrivendo, più tempo ci vuole per rileggere …

Dal momento che la tua app è un’app Rails, ti suggerirei entrambi:

  1. Utilizzando la capacità dei tuoi clienti di memorizzare nella cache memorizzando le carte in javascript. (per eseguire questa operazione è necessaria un’app piuttosto ajaxy, vedere l’ultimo RailsCast per alcuni punti interessanti sulla memorizzazione nella cache delle pagine javascript)
  2. Utilizzare una delle tante opzioni di caching lato server supportate da rotaie (ad esempio MemCached) per memorizzare questi dati nella cache.

Un problema molto più insidioso che incontrerai nella memorizzazione degli oggetti direttamente nella sessione è quando utilizzi CookieStore (il valore predefinito in Rails 2+ credo). È molto facile ottenere errori di CookieOverflow che sono molto difficili da recuperare.