2012-12-03 13 views
6

私はページ全体にレンダリングされたいくつかの部分的な部分を持つホームページを持っています。また、セッションヘッダも持っています(ログイン)。 部分には改ページされた書籍のセットが含まれています。今は週に1回更新されるので、この部分をキャッシュします。特定の部分的なレールをキャッシュする3.0.x

  • 質問1:この特定の部分をキャッシュするにはどうすればよいですか( dbになることなく)?
  • 質問2: 書籍のモデルを更新すると、キャッシュされたコンテンツを削除(有効期限切れ)するにはどうすればよいですか?

答えて

8

ここでは、ビューレイヤーで発生するfragment cachingを探しています。フラグメントのキャッシュと格納されたコンテンツの有効期限は、驚くほど簡単です。 、このコースを

<% cache do %> 
    <ul> 
    <% @books.each do |book| %> 
     <li><%= book.name %></li> 
    <% end %> 
    </ul> 
<% end %> 

:あなたは本のリストを持っているので、のは、あなたのビューは、このようなビットに見えるとしましょう:

<ul> 
    <% @books.each do |book| %> 
    <li><%= book.name %></li> 
    <% end %> 
</ul> 

は単にcacheでそれをラップし、ちょうどこのビットのキャッシュを有効にするにはキャッシュに名前をつけたり、何か本当に特別なことをしたりしません.Railsはこのキャッシュフラグメントの一意の名前を自動的に選択しますが、それは本当に役立たないでしょう。私たちはより良いことができます。 DHHのkey-based cache expiration技術を使用して、キャッシュにそのコンテンツに関連する名前を付けましょう。キャッシュに引数を渡す

<% cache ['book-list', *@books] do %> 
    <ul> 
    <% @books.each do |book| %> 
     <li><%= book.name %></li> 
    <% end %> 
    </ul> 
<% end %> 

は、指定された引数からキャッシュキーを作成します。文字列は直接渡されるので、ここではキャッシュは常に 'book-list'で始まります。これは、同じコンテンツをキャッシングしている可能性がある他の場所とのキャッシュの衝突を防ぐためですが、ビューは異なります。 @books配列の各メンバに対して、Railsはcache_keyを呼び出します:ActiveRecordオブジェクトの場合、モデルIDから構成された文字列が生成され、オブジェクトが最後に更新されたときに決定的に反映されます。

これは、オブジェクトを更新すると、このフラグメントのキャッシュキーが変更されることを意味します。つまり、自動的に期限切れになる - 本が更新されると、このキャッシュステートメントは存在しないキーを検索し、存在しないと判断して新しいコンテンツを設定します。古くなった古くなったコンテンツは、メモリや年齢の制約によって退去されるまでキャッシュストアに残ります(memcachedはこれを自動的に行います)。

私は、この技術を数多くのプロダクションアプリケーションで使用しています。詳細については、37signals postをチェックし、Railsの一般的なキャッシング情報については、Ruby on Rails caching guideを参照してください。

+0

1:

# controller_method @weekly_books = Books.where 'condition' # _partial.html.erb <% cache(@weekly_books) do %> <%# ... content %> <% end %> 

しばしばあなたも呼び出しをラップすることにより、クエリ自己をキャッシュすることができますし、DBを打つ避けるために。私は通常、テーブル全体で最も最近更新された本のレコードをつかみ、それを使用します。 – cpuguy83

+0

変更されたブックがキャッシュ全体を壊さないように、個々のブックをキャッシュする必要があります。 – cpuguy83

4

"コンピュータサイエンスには2つの困難な問題があります: キャッシュの無効化と名前の付け方です。"
- フィルKarlton

キャッシュ


Rails Guide to cachingは、キャッシング戦略に組み込まれたレールのための優れたエントリー・ポイントを提供している、おそらく常にあります。とにかく、ここでのキャッシングに私は非常に簡単なアプローチ

# _partial.html.erb 
<% cache(some_key, :expires_in => 1.week) do %> 
    <%# ... content %> 
<% end %> 

は現在、いくつかのsome_keyは限りそれが一意であるとして任意の文字列にすることができています。しかしもう一度やり直してみると、もう少し賢いようにして、キーを何とか書籍のリストに依存させるようにしています。実際にbooksの配列を渡して、いくつかのクエリが返された後、各エントリでという呼び出しを呼び出し、最終的にこのコレクションの一意のキーを構築します。コレクションが変更されると、キーが変更されます。 cache_keyActiveRecord::Baseに実装されているため、すべてのモデルで利用可能です。また、利用可能であれば、タイムスタンプも使用します。

もう一度これは、要求が行われるたびにdbに当たるでしょう。コード内 同じ:@booksコレクションをスプラッティングの

# Book.rb 
def self.weeklies 
    Rails.cache.fetch("book_weeklies", :expires_in => 1.day) do 
    Books.where 'condition' 
    end 
end 

# controller_method 
@weekly_books = Books.weeklies 

# _partial.html.erb 
<% cache(@weekly_books) do %> 
    <%# ... content %> 
<% end %> 
+0

問題は私のホームページにあります。本は改ページされています。私はページ分けされた本を部分に送る。今ではBooks.weekliesを使用すると、ページ単位のレコードは得られません。それを達成する方法? –

関連する問題