Après avoir étudié DHH et d'autres articles de blog sur l'expiration du cache basée sur les clés et la mise en cache de poupées russes, je ne sais toujours pas comment gérer un type de relation. Pour être précis, une relation has_many
. Je vais partager les résultats de mes recherches sur un exemple d'application. C'est un peu l'histoire, alors attendez. Disons que nous avons les modèles ActiveRecord suivants. Tout ce qui nous intéresse est un changement approprié de la cache_key
du modèle, non?Structuration d'une application Rails pour Russian Doll Caching avec une relation has_many
class Article < ActiveRecord::Base
attr_accessible :author_id, :body, :title
has_many :comments
belongs_to :author
end
class Comment < ActiveRecord::Base
attr_accessible :article_id, :author_id, :body
belongs_to :author
belongs_to :article, touch: true
end
class Author < ActiveRecord::Base
attr_accessible :name
has_many :articles
has_many :comments
end
Nous avons déjà un article, avec un commentaire. Tous deux par un auteur différent. L'objectif est d'avoir un changement dans le cache_key
de l'article dans les cas suivants:
- corps de l'article ou titre change
- Son corps de commentaire change
- article nom de de l'auteur change
- article le nom de de commentaire auteur changements
donc, par défaut, nous sommes bons pour le cas 1 et 2.
1.9.3-p194 :034 > article.cache_key
=> "articles/1-20130412185804"
1.9.3-p194 :035 > article.comments.first.update_attribute('body', 'First Post!')
1.9.3-p194 :038 > article.cache_key
=> "articles/1-20130412185913"
Mais pas pour le cas 3.
1.9.3-p194 :040 > article.author.update_attribute('name', 'Adam A.')
1.9.3-p194 :041 > article.cache_key
=> "articles/1-20130412185913"
Définissons une méthode cache_key
composite pour Article
.
class Article < ActiveRecord::Base
attr_accessible :author_id, :body, :title
has_many :comments
belongs_to :author
def cache_key
[super, author.cache_key].join('/')
end
end
1.9.3-p194 :007 > article.cache_key
=> "articles/1-20130412185913/authors/1-20130412190438"
1.9.3-p194 :008 > article.author.update_attribute('name', 'Adam B.')
1.9.3-p194 :009 > article.cache_key
=> "articles/1-20130412185913/authors/1-20130412190849"
Win! Mais bien sûr, cela ne fonctionne pas pour le cas 4.
1.9.3-p194 :012 > article.comments.first.author.update_attribute('name', 'Bernard A.')
1.9.3-p194 :013 > article.cache_key
=> "articles/1-20130412185913/authors/1-20130412190849"
Alors quelles sont les options à gauche? Nous pourrions faire quelque chose avec l'association has_many
sur Author
, mais has_many
ne prend pas l'option {touch: true}
, et probablement pour une raison. Je suppose que cela pourrait être mis en œuvre de la façon suivante.
class Author < ActiveRecord::Base
attr_accessible :name
has_many :articles
has_many :comments
before_save do
articles.each { |record| record.touch }
comments.each { |record| record.touch }
end
end
article.comments.first.author.update_attribute('name', 'Bernard B.')
article.cache_key
=> "articles/1-20130412192036"
Bien que cela ne fonctionne pas. Il a un énorme impact sur les performances, en chargeant, instanciant et mettant à jour chaque article et en faisant des commentaires par cet autre, un par un. Je ne crois pas que ce soit une bonne solution, mais qu'est-ce que c'est?
Bien sûr, le cas d'utilisation de 37 signaux/exemple peut être différent: project -> todolist -> todo
. Mais j'imagine un seul objet todo appartenant également à un utilisateur.
Comment pourrait-on résoudre ce problème de mise en cache?
Cela ne répond pas à la question de la mise en cache spécifique, mais la mise en œuvre tactile ne doit pas être si intense. Vous pourriez simplement faire quelque chose comme 'articles.update_all (updated_at: Time.now)', ce qui donnerait un op pour les articles (et un pour les commentaires). – numbers1311407
@ numbers1311407 Le problème avec cette méthode est que 'update_all' n'exécute que SQL, aucun callback n'est effectué, donc les' touch'es suivantes ne se produiront pas, et 'cache_key's dans les objets mémoire ne sont pas régénérés. –
Bien sûr, mais la mise à jour automatique des objets en mémoire est-elle vraiment votre préoccupation? C'est un problème dans la console rails, mais généralement pas dans le monde réel où l'auteur change son nom en une seule action, alors lui et d'autres sont en train de rendre des vues de commentaires dans un autre. Si vous vous trouvez dans une situation où vous avez besoin d'actualiser la clé de cache sur un objet en mémoire, rechargez-la simplement. – numbers1311407