2009-03-19 15 views
11

C'è un modo per memorizzare nella cache i dati per richiesta in Rails? Per una determinata richiesta Rails/mongrel ho il risultato di un'operazione semi-costosa a cui vorrei accedere più volte in quella richiesta. C'è un hash in cui posso memorizzare e accedere a tali dati?Rails per richiesta di hash?

Deve essere abbastanza globale e accessibile da visualizzazioni, controller e librerie, come Rails.cache e I18n.

Sto bene facendo qualche patch di scimmia se è quello che serve.

  • Memcached non funziona perché verrà condiviso tra richieste, che non desidero.
  • Una variabile globale in modo simile non funziona perché richieste diverse condividono gli stessi dati, che non è quello che voglio.
  • Le variabili di istanza non funzionano perché desidero accedere ai dati da classi diverse.
+0

Tu dici che vuoi che sia condiviso tra le richieste (punto 1), ma anche che non si desidera richieste condividerlo (proiettile 2). Penso di sapere cosa intendi, ma dovresti chiarire. –

+0

Nel punto 1 dico che non lo voglio condividere con le richieste. –

risposta

4

Prova PerRequestCache. Ho rubato il design da SQL Query Cache.

configurarlo in config/environment.rb con:

config.middleware.use PerRequestCache 

poi utilizzarlo con:

PerRequestCache.fetch(:foo_cache){ some_expensive_foo } 
+0

Come suggerisce il tuo suggerimento, non è sicuro per i thread. Ho appena finito di immagazzinare roba direttamente nella cache di query SQL. È un hack, ma funziona. –

1

Le variabili globali sono malvagie. Elabora come passare in modo pulito i dati che desideri dove vuoi utilizzarli.

+5

Non è sempre pratico. Come ho già detto, Rails ha oggetti globali come Rails.cache e I18n. –

0

Hai considerato il flash? Usa Session ma viene automaticamente cancellato.

-3

app/modelli/my_cacher.rb

class MyCacher 
    def self.result 
    @@result ||= begin 
     # do expensive stuff 
     # and cache in @@result 
    end 
    end 
end 

Il || = sintassi in pratica significa "fare quanto segue se @@ risultato è pari a zero" (vale a dire non impostato ancora nulla). Assicurati solo che l'ultima riga nel blocco inizio/fine restituisca il risultato.

Poi nelle viste/modelli/ciò che più vi basta fare riferimento alla funzione in caso di necessità:

MyCacher.result 

Ciò cache l'azione costoso per la durata di una richiesta.

+4

Questo verrà memorizzato nella cache per la durata dell'istanza dell'app (molte richieste) in modalità produzione. – cwninja

0

Memoisation?

Secondo this railscast è memorizzato per richiesta.

+2

Memoria sul metodo di classe verrà memorizzata nella cache per tutto il tempo. Memoria su un'istanza verrà memorizzata nella cache per tutta la durata dell'istanza. L'eccessiva memorizzazione nella cache delle classi blocca la memoria. Ho rimosso le scatole di produzione facendo questo errore. – cwninja

4

C'è anche la request_store gemma.Dalla documentazione:

aggiungere questa linea al Gemfile dell'applicazione:

gem 'request_store' 

e utilizzando questo codice per memorizzare e recuperare i dati (limitati alla richiesta):

# Set 
RequestStore.store[:foo] = 0 

# Get 
RequestStore.store[:foo] 
+0

La gemma risolve praticamente l'intero problema. Ho aggiunto alcune istruzioni per l'uso, ma fondamentalmente non c'è molto di più. –

+0

Non dovresti usare questa gemma con un server threadato come Thin o Puma. – Papipo

+0

@Papipo La documentazione di questa gemma si definisce esplicitamente come un'alternativa funzionale a 'Thread.current' per i server con thread come Thin e Puma. – James

1

Uno dei più le opzioni più comuni sono l'uso della gemma request_store, che ti consente di accedere a un negozio globale che provi da qualsiasi parte del tuo codice. Utilizza Thread.current per memorizzare i dati e si occupa della pulizia dei dati dopo ogni richiesta.

RequestStore[:items] = [] 

Attenzione però, in quanto utilizza Thread.current, non funzionerà correttamente in un ambiente multi-threaded in cui si dispone di più di un thread per ogni richiesta.

Per ovviare a questo problema, ho implementato un negozio che può essere condiviso tra thread per la stessa richiesta. Si chiama request_store_rails, è thread-safe, e l'utilizzo è molto simile:

RequestLocals[:items] = [] 
Problemi correlati