キーベースのキャッシュの有効期限とロシアン ドール キャッシングに関する DHH や他のブログ記事を調べた後でも、1 つのリレーション タイプを処理する方法がわかりません。具体的に言えば、has_many
関係。
サンプルアプリでの調査結果を共有します。ちょっとした話ですので、ちょっと待ってください。次の ActiveRecord モデルがあるとします。私たちが気にかけているのは、モデルの を適切に変更することだけcache_key
ですよね?
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
すでに 1 つの記事と 1 つのコメントがあります。どちらも別作者。目標はcache_key
、次の場合に記事の を変更することです。
- 記事の本文またはタイトルの変更
- コメントの本文が変更されます
- 記事の著者名の変更
- 記事のコメントの作者名が変わります
したがって、デフォルトでは、ケース 1 と 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"
ただし、ケース 3 には当てはまりません。
1.9.3-p194 :040 > article.author.update_attribute('name', 'Adam A.')
1.9.3-p194 :041 > article.cache_key
=> "articles/1-20130412185913"
cache_key
の複合メソッドを定義しましょう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"
勝つ!しかしもちろん、これはケース 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"
では、どのようなオプションが残っていますか?has_many
上のアソシエーションを使用して何かを実行できますAuthor
がhas_many
、オプションを使用しません{touch: true}
。おそらく理由があります。次の行に沿って多少実装できると思います。
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"
これは機能しますが。すべての記事とコメントを1 つずつ読み込み、インスタンス化、更新することで、パフォーマンスに大きな影響を与えます。それが適切な解決策だとは思いませんが、それは何ですか?
確かに 37signals の使用例 / 例は異なる場合があります: project -> todolist -> todo
. しかし、1 つの todo アイテムもユーザーに属していると思います。
このキャッシュの問題をどのように解決しますか?