16.3 Action-Caching 

Grundlagen 

In unserem Beispiel für das Page-Caching haben wir dieses für die Actions index und show des Products-Controllers aktiviert. Der Geschwindigkeitsvorteil ist in diesem Fall enorm, denn sobald die Seiten im Cache gespeichert sind, liefert der Webserver sie direkt aus, ohne dass dabei Rails involviert wird.
Abbildung Grundprinzip des Action-Caching
Problem
Das stellt uns aber in bestimmten Fällen vor ein Problem. Angenommen, wir möchten Seiten mit einem Passwortschutz versehen. Nur Benutzer, die authentifiziert sind, sollen Zugriff auf diese Seiten haben. Ist der Benutzer nicht authentifiziert, so soll sich ein Log-in-Fenster öffnen.
Before-Filter
In diesem Fall bietet es sich an, das Action-Caching zu verwenden. Beim Action-Caching werden auch die Ausgaben der entsprechenden Actions wie beim Page-Caching in einer Datei abgelegt. Jedoch gibt es hier einen wesentlichen Unterschied. Beim Action-Caching wird Rails involviert, auch wenn eine passende Cache-Datei vorhanden ist. Rails prüft vor Auslieferung der entsprechenden Cache-Datei, ob für die aufgerufene Action ein (Before-)Filter vorliegt. Ein Before-Filter ist eine Methode im Controller, die vor Ausführung einer Action aufgerufen wird und z. B. überprüft, ob ein User authentifiziert ist. Wenn der Before-Filter eine Weiterleitung macht oder eine Ausgabe generiert, wird die eigentliche Action nicht aufgerufen. Wichtig ist, dass die Action selbst nicht ausgeführt wird, außer es liegt noch keine Cache-Datei für die Action vor.
Cache-Dateien
Ein weiterer Unterschied ist, dass die Cache-Dateien nicht standardmäßig im public -Verzeichnis gespeichert werden, sondern im Verzeichnis tmp/cache . Der Grund dafür liegt darin, dass der Webserver keinen Zugriff auf die Cache-Dateien haben soll. Nur Rails soll für die Auslieferung der Action-Cache-Dateien zuständig sein.
Beispiel 

Wir setzen im Folgenden das Beispiel aus dem letzten Abschnitt fort. Um zu demonstrieren, dass das Page-Caching nicht ausreicht, ergänzen wir unsere Applikation. Der Zugriff soll per Authentifizierung geschüzt werden. Wir setzen dazu die HTTP-Authentifizierung, die per Before-Filter im Controller eingebunden wird, ein. Bei jedem Aufruf einer Action wird vor der Ausführung die Authentifizierung ausgeführt.
Listing app/controllers/products
class ProductsController < ApplicationController before_filter :authenticate caches_page :index, :show cache_sweeper :product_sweeper, :only => [:update, :create, :destroy] ... private def authenticate authenticate_or_request_with_http_basic do |user,password| user=="admin" && password=="geheim3" end end end
Das Problem ist, dass bei der Verwendung des Page-Caching der Before-Filter nur ausgeführt wird, wenn die betroffene Action entweder noch nicht gecached ist oder für das Page-Caching ausgenommen wird. Im Beispiel werden nur die Actions index und show im Cache gespeichert.
caches_page
Um das Problem zu lösen, ersetzen wir das Page-Caching durch das Action-Caching, indem wir im Products-Controller den Befehl caches_page durch caches_action ersetzen.
Listing app/controllers/products
class ProductsController < ApplicationController
before_filter :authenticate
caches_action :index, :show
cache_sweeper :product_sweeper,
:only => [:update, :create, :destroy]
...
end
Wie bereits erwähnt, befinden sich die Cache-Dateien im Verzeichnis tmp/cache/servername . Der Servername ist in unserem Fall localhost.
Abbildung tmp-Verzeichnis mit den Cache-Dateien
Wie beim Page-Caching müssen wir uns auch beim Action-Caching um das Löschen der Cache-Dateien kümmern.
Löschen von Cache-Dateien 

Die Cache-Dateien im Verzeichnis tmp/cache können entweder manuell, mit einem Rake-Task oder per Befehl im Controller bzw. in einem Sweeper gelöscht werden.
Rake-Tasks
Im Gegensatz zum Page-Caching wird Rails bereits mit einem passenden Rake-Task rake tmp:cache:clear ausgeliefert, der sämtliche Cache-Dateien entfernt. Alternativ können Sie auch den Rake-Task rake tmp:clear einsetzen, der nicht nur den Cache leert, sondern auch die Socket- und Session-Dateien im tmp -Verzeichnis löscht.
expire_page
Im Controller bzw. in einem Sweeper kann der Befehl expire_action statt expire_page eingesetzt werden (siehe Abschnitt 16.2.5 ). Eine weitere wichtige Änderung ist, dass der Befehl expire_action eine URL mit einem absoluten Pfad erwartet. Daher verwenden wir z. B. products_url statt products_path . Dies ist deshalb erforderlich, weil im Verzeichnis tmp/cache ein Verzeichnis mit dem Server-Namen gespeichert wird. Wenn wir die Applikation lokal ausführen, ist es das Verzeichnis localhost.3000.
Wir ändern dazu die Sweeper-Datei product_sweeper.rb im Verzeichnis app/models entsprechend ab:
Listing app/models/product_sweeper.rb
class ProductSweeper < ActionController::Caching::Sweeper observe Product def after_save(product) expire_products(product) end def after_destroy(product) expire_products(product) end private def expire_products(product) expire_action(product_url(product)) expire_action(products_url) end end
expire_index
Die Methode expire_index zum Löschen der Datei public/index.html ist nicht mehr nötig, da die Cache-Datei aufgrund des Action-Caching nicht mehr generiert wird.
Verschiedene Caching-Strategien mischen 

Es ist auch möglich, die verschiedenen Caching-Strategien zu mischen. Im folgenden Beispiel wird für die index -Action das Action-Caching und für die show -Action das Page-Caching verwendet.
Listing app/controllers/products
class ProductsController < ApplicationController before_filter :authenticate caches_action :index caches_page :show ... end
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.