Ruby on Rails
caching
Ricerca…
Caching di bambole russe
Si consiglia di nidificare i frammenti memorizzati nella cache all'interno di altri frammenti memorizzati nella cache. Questo è chiamato Russian doll caching
.
Il vantaggio del Russian doll caching
è che se un singolo prodotto viene aggiornato, tutti gli altri frammenti interni possono essere riutilizzati durante la rigenerazione del frammento esterno.
Come spiegato nella sezione precedente, un file memorizzato nella cache scadrà se il valore di updated_at
cambia per un record dal quale dipende direttamente il file memorizzato nella cache. Tuttavia, questo non farà scadere alcuna cache all'interno della quale il frammento è annidato.
Ad esempio, prendere la seguente vista:
<% cache product do %>
<%= render product.games %>
<% end %>
Che a sua volta rende questa vista:
<% cache game do %>
<%= render game %>
<% end %>
Se viene modificato qualsiasi attributo di gioco, il valore updated_at
verrà impostato sull'ora corrente, con conseguente scadenza della cache.
Tuttavia, poiché updated_at
non verrà modificato per l'oggetto prodotto, tale cache non sarà scaduta e la tua app fornirà dati obsoleti. Per risolvere questo problema, leghiamo i modelli insieme al metodo touch:
class Product < ApplicationRecord
has_many :games
end
class Game < ApplicationRecord
belongs_to :product, touch: true
end
Cache SQL
La cache di query è una funzionalità di Rails
che memorizza nella cache il set di risultati restituito da ogni query. Se Rails
riscontra nuovamente la stessa query per quella richiesta, utilizzerà il set di risultati memorizzato nella cache anziché eseguire nuovamente la query sul database.
Per esempio:
class ProductsController < ApplicationController
def index
# Run a find query
@products = Product.all
...
# Run the same query again
@products = Product.all
end
end
La seconda volta che la stessa query viene eseguita sul database, non sta andando a colpire il database. La prima volta che il risultato viene restituito dalla query, viene memorizzato nella cache della query (in memoria) e la seconda volta viene estratto dalla memoria.
Tuttavia, è importante notare che le cache di query vengono create all'inizio di un'azione e distrutte alla fine di tale azione e quindi rimangono attive solo per la durata dell'azione. Se desideri memorizzare i risultati della query in modo più persistente, puoi farlo con la memorizzazione nella cache di basso livello.
Frammento di cache
Rails.cache
, fornito da ActiveSupport, può essere utilizzato per memorizzare nella cache qualsiasi oggetto Ruby serializzabile tra le richieste.
Per recuperare un valore dalla cache per una determinata chiave, utilizzare cache.read
:
Rails.cache.read('city')
# => nil
Usa cache.write
per scrivere un valore nella cache:
Rails.cache.write('city', 'Duckburgh')
Rails.cache.read('city')
# => 'Duckburgh'
In alternativa, utilizza cache.fetch
per leggere un valore dalla cache e facoltativamente scrivere un valore predefinito se non esiste alcun valore:
Rails.cache.fetch('user') do
User.where(:is_awesome => true)
end
Il valore di ritorno del blocco passato verrà assegnato alla cache sotto la chiave specificata e quindi restituito.
Puoi anche specificare una scadenza cache:
Rails.cache.fetch('user', :expires_in => 30.minutes) do
User.where(:is_awesome => true)
end
Memorizzazione nella cache della pagina
Puoi utilizzare il pacchetto Action_Pack_caching gem per memorizzare nella cache le singole pagine. Questo memorizza il risultato di una richiesta dinamica come un file HTML statico, che viene servito al posto della richiesta dinamica sulle richieste successive. Il README contiene le istruzioni complete di impostazione. Una volta impostato, utilizzare il metodo di classe caches_page
in un controller per memorizzare nella cache il risultato di un'azione:
class UsersController < ActionController::Base
caches_page :index
end
Usa expire_page
per forzare la scadenza della cache eliminando il file HTML memorizzato:
class UsersController < ActionController::Base
caches_page :index
def index
@users = User.all
end
def create
expire_page :action => :index
end
end
La sintassi di expire_page
riproduce quella di url_for
e degli amici.
Caching HTTP
Rails> = 3 viene fornito con le funzionalità di caching HTTP fuori dalla scatola. Questo utilizza le intestazioni Cache-Control
e ETag
per controllare per quanto tempo un client o un intermediario (come una CDN) può memorizzare nella cache una pagina.
In un'azione del controllore, usa expires_in
per impostare la lunghezza della cache per quell'azione:
def show
@user = User.find params[:id]
expires_in 30.minutes, :public => true
end
Usa expires_now
per forzare la scadenza immediata di una risorsa memorizzata nella cache su qualsiasi cliente o intermediario in visita:
def show
@users = User.find params[:id]
expires_now if params[:id] == 1
end
Caching delle azioni
Come la memorizzazione nella cache delle pagine, il caching delle azioni memorizza nella cache l'intera pagina. La differenza è che la richiesta colpisce lo stack Rails, quindi prima che i filtri vengano eseguiti prima che la cache venga pubblicata. Viene estratto da Rails nella gemma actionpack-action_caching .
Un esempio comune è il caching di un'azione che richiede l'autenticazione:
class SecretIngredientsController < ApplicationController
before_action :authenticate_user!, only: :index, :show
caches_action :index
def index
@secret_ingredients = Recipe.find(params[:recipe_id]).secret_ingredients
end
end
Le opzioni includono :expires_in
, una custom :cache_path
(per le azioni con più route che devono essere memorizzate nella cache in modo diverso) e :if
/ :unless
che :unless
controlli quando l'azione deve essere memorizzata nella cache.
class RecipesController < ApplicationController
before_action :authenticate_user!, except: :show
caches_page :show
caches_action :archive, expires_in: 1.day
caches_action :index, unless: { request.format.json? }
end
Quando il layout ha un contenuto dinamico, memorizza nella cache solo il contenuto dell'azione passando il layout: false
.