Defekte Links, wenn dabei Fragment-Caching in Rails
-
11-10-2019 - |
Frage
Angenommen, es ist ein Blog mit den Beiträgen, Kommentaren und Benutzer, die kommentieren. Die Benutzer haben SEO-freundliche URLs wie http: // localhost: 3000 / users / john (dies kann sein leicht gemacht durch permalink_fu verwendet wird).
Das Modell verwendet berühren zu vereinfachen Caching:
class Post
has_many :comments
end
class Comment
belongs_to :post, :touch=>true
end
Und der Blick Code so etwas wie dieses wäre:
<%= cache @post do %>
<h1><%= @post.title %></h1>
<%= @post.content %>
<%= @post.comments.each do |comment| %>
<%= link_to h(comment.user), comment.user %> said:
<%= comment.content %>
<% end %>
<% end %>
Nehmen wir nun an John ändert seinen nick zu Johnny - seine URL Änderungen an http: // localhost: 3000 / users / johnny . Da Fragment-Caching auf Beiträge zu tun und Kommentare werden Johns Kommentare zu Johns falsche URL verweisen, es sei denn das Fragment abgelaufen ist. Es kann möglich sein, manuell zu berühren oder alle Beiträge verfallen, die Kommentare von John in diesem Beispiel enthält, aber in einer komplexen Anwendung dies erfordern würde sehr komplexe Abfragen und scheint sehr fehleranfällig ist.
Was ist die beste Praxis hier? Sollte ich nicht-SEO-freundliche URLs wie / users / 13 statt / users / john? Oder vielleicht eine Liste von alten URLs halten, bis der Cache abgelaufen ist? Keine Lösung sieht gut aus für mich.
EDIT: Bitte beachten Sie, dies ist nur ein vereinfachtes Beispiel - es Abfrage Beiträge auf jeden Fall sehr einfach ist und sie in diesem Fall berühren. Aber eine komplexe app impliziert zwischen Objekten viele Beziehungen, die es schwer machen, jedes Objekt zu verfolgen, die einen Verweis auf einen Benutzer hat. Ich habe ein bisschen auf das erforschte -. Facebook ermöglicht es nur Ihren Benutzernamen einmal einstellen, so dass dieses Problem existiert nicht
Lösung
Ich sehe nicht, dass es kompliziert sein gecached Beiträge verfallen. Richten Sie eine Kehrmaschine:
class UserSweeper < ActionController::Caching::Sweeper
observe User
def after_save(user)
user.comments.collect(&:post).each do |post|
expire_fragment post
end
end
Andere Tipps
ich einen BEFORE_SAVE Filter zum Beispiel verwenden würde
class User
has_many :posts
before_save :touch_posts
private
def touch_posts
Post.update_all({:updated_at => Time.now}, {:user_id => self.id}) if self.login_changed?
true
end
end
Eine Abfrage eines jeden Benutzers Beitrag zu aktualisieren. Nicht wirklich komplex.