Ruby on Rails
Mise en cache
Recherche…
Poupée Russe Caching
Vous souhaiterez peut-être imbriquer des fragments en cache dans d'autres fragments mis en cache. Cela s'appelle Russian doll caching
.
L'avantage de Russian doll caching
est que si un seul produit est mis à jour, tous les autres fragments internes peuvent être réutilisés lors de la régénération du fragment externe.
Comme expliqué dans la section précédente, un fichier mis en cache expirera si la valeur de updated_at
change pour un enregistrement dont dépend directement le fichier en cache. Cependant, cela n'expire aucun cache dans lequel le fragment est imbriqué.
Par exemple, prenez la vue suivante:
<% cache product do %>
<%= render product.games %>
<% end %>
Qui à son tour rend cette vue:
<% cache game do %>
<%= render game %>
<% end %>
Si un attribut de jeu est modifié, la valeur updated_at
sera définie sur l'heure actuelle, expirant ainsi le cache.
Cependant, parce que updated_at
ne sera pas modifié pour l'objet produit, ce cache ne sera pas expiré et votre application servira les données obsolètes. Pour résoudre ce problème, nous lions les modèles avec la méthode tactile:
class Product < ApplicationRecord
has_many :games
end
class Game < ApplicationRecord
belongs_to :product, touch: true
end
Mise en cache SQL
La mise en cache des requêtes est une fonctionnalité Rails
qui met en cache l'ensemble de résultats renvoyé par chaque requête. Si Rails
rencontre à nouveau la même requête pour cette requête, il utilisera le jeu de résultats mis en cache au lieu d'exécuter à nouveau la requête sur la base de données.
Par exemple:
class ProductsController < ApplicationController
def index
# Run a find query
@products = Product.all
...
# Run the same query again
@products = Product.all
end
end
La deuxième fois que la même requête est exécutée sur la base de données, elle ne touchera pas réellement la base de données. La première fois que le résultat est renvoyé par la requête, il est stocké dans le cache de la requête (en mémoire) et la deuxième fois dans la mémoire.
Cependant, il est important de noter que les caches de requêtes sont créés au début d'une action et détruits à la fin de cette action et ne persistent donc que pendant la durée de l'action. Si vous souhaitez stocker les résultats de la requête de manière plus persistante, vous pouvez utiliser la mise en cache de bas niveau.
Mise en cache des fragments
Rails.cache
, fourni par ActiveSupport, peut être utilisé pour mettre en cache tout objet Ruby sérialisable dans les requêtes.
Pour extraire une valeur du cache pour une clé donnée, utilisez cache.read
:
Rails.cache.read('city')
# => nil
Utilisez cache.write
pour écrire une valeur dans le cache:
Rails.cache.write('city', 'Duckburgh')
Rails.cache.read('city')
# => 'Duckburgh'
Vous pouvez également utiliser cache.fetch
pour lire une valeur du cache et éventuellement écrire une valeur par défaut s'il n'y a pas de valeur:
Rails.cache.fetch('user') do
User.where(:is_awesome => true)
end
La valeur de retour du bloc passé sera attribuée au cache sous la clé donnée, puis renvoyée.
Vous pouvez également spécifier une expiration du cache:
Rails.cache.fetch('user', :expires_in => 30.minutes) do
User.where(:is_awesome => true)
end
Mise en cache de page
Vous pouvez utiliser le joyau ActionPack page_caching pour mettre en cache des pages individuelles. Cela stocke le résultat d'une requête dynamique en tant que fichier HTML statique, qui est utilisé à la place de la demande dynamique lors des requêtes suivantes. Le fichier README contient des instructions de configuration complètes. Une fois configuré, utilisez la méthode de classe caches_page
dans un contrôleur pour mettre en cache le résultat d'une action:
class UsersController < ActionController::Base
caches_page :index
end
Utilisez expire_page
pour forcer l'expiration du cache en supprimant le fichier HTML stocké:
class UsersController < ActionController::Base
caches_page :index
def index
@users = User.all
end
def create
expire_page :action => :index
end
end
La syntaxe de expire_page
imite celle de url_for
et des amis.
Mise en cache HTTP
Rails> = 3 est livré avec des capacités de mise en cache HTTP prêtes à l'emploi. Cela utilise les en Cache-Control
têtes Cache-Control
et ETag
pour contrôler la durée pendant laquelle un client ou un intermédiaire (tel qu'un CDN) peut mettre en cache une page.
Dans une action de contrôleur, utilisez expires_in
pour définir la longueur de la mise en cache pour cette action:
def show
@user = User.find params[:id]
expires_in 30.minutes, :public => true
end
Utilisez expires_now
pour forcer l'expiration immédiate d'une ressource en cache sur tout client ou intermédiaire en visite:
def show
@users = User.find params[:id]
expires_now if params[:id] == 1
end
Mise en cache des actions
Comme pour la mise en cache des pages, la mise en cache des actions met en cache toute la page. La différence est que la requête frappe la pile Rails avant que les filtres ne soient exécutés avant que le cache ne soit servi. Il est extrait de Rails à la gem actionpack-action_caching .
Un exemple courant est la mise en cache d'une action nécessitant une authentification:
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
Les options incluent :expires_in
, un :expires_in
personnalisé :cache_path
(pour les actions avec plusieurs routes devant être mises en cache différemment) et :if
/ :unless
pour contrôler quand l'action doit être mise en 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
Lorsque la mise en page a un contenu dynamique, ne mettez en cache que le contenu de l’action en passant la layout: false
en layout: false
.