RailCast episode 172 - Touch and Cache


Railsは最近2.3.3版にアップグレードされた.今回は小さなアップグレードにすぎませんが、主に以前のバージョンのいくつかのエラー修正(bug fixes)について、この新しいバージョンは私たちにいくつかの新しい特性(features)を提供してくれました.Touchはその中の1つです.このセットでは、touchを使用してアプリケーションのキャッシュを改善する方法を説明します.
レイルズを2.3.3にアップグレードしていない場合は、コマンドラインで実行できます.
sudo gem update rails
新しいバージョンにアップグレードするアップグレードしたいアプリケーションで/config/enrionmentを変更できます.rbファイルの一番上の行:

   1. # Specifies gem version of Rails to use when vendor/rails is not present  
   2. RAILS_GEM_VERSION = '2.3.3' unless defined? RAILS_GEM_VERSION  

アプリケーションをアップグレードする準備ができている場合は、アプリケーションに優れたテストキット(test suite)があることを確認します.これにより、アップグレードが既存のアプリケーションを破壊しないことを保証できます.
クリップキャッシュ(Fragment Caching)とともにtouchを使用する
  
以下に、ブログアプリケーションのarticleページを示します.このページのトラフィックが大きいので、彼の性能を改善したいと思っています.
クリップキャッシュ(Fragment Caching)を追加して、ページの時間を短縮することができます.これは最も理想的な解決策ではないかもしれませんが、問題を迅速に解決することができます.まず、このページにクリップキャッシュ(Fragment Caching)を適用してみましょう.
開発モードでは、キャッシュはデフォルトで無効になっています.まずキャッシュを開きます./config/environments/defaultを変更する必要があります.rbファイル:
config.action_controller.perform_caching = true

もう1つの方法は、一時環境(staging environment)を作成することである.一時環境の作成方法についてもっと知りたい場合は、
第72話 . 一時環境(staging environment)を作成した場合は、開発環境でキャッシュをアクティブまたは無効にする必要はありません.
フラグメントキャッシュ(fragment caching)はarticleのshowビューに追加されます.ビューコードは次のとおりです.

<% title @article.name %>  
<p class="author"><em>from <%=h @article.author_name %></em></p>  
<%= simple_format @article.content %>  
<p><%= link_to "Back to Articles", articles_path %></p>  
<% unless @article.comments.empty? %>  
  <h2><%= pluralize(@article.comments.size, 'comment') %></h2>  
  <div id="comments">  
  <% for comment in @article.comments %>  
    <div id="comment">  
      <strong><%= link_to_unless comment.site_url.blank?, h(comment.author_name), h(comment.site_url) %></strong>  
      <em>on <%= comment.created_at.strftime('%b %d, %Y at %H:%M') %></em>  
      <%= simple_format comment.content %>  
    </div>  
  <% end %>  
  </div>  
<% end %>  
<h3>Add your comment:</h3>  
<%= render :partial => 'comments/form' %>  

cacheメソッドを呼び出し、キャッシュするクリップをキャッシュブロックに含めます.

<% title @article.name %>  
<% cache @article do %>  
  <p class="author"><em>from <%=h @article.author_name %></em></p>  
  <!-- Rest of code omitted -->  
<% end %>  
<h3>Add your comment:</h3>  
<%= render :partial => 'comments/form' %>  

Cacheメソッドは、オプションのパラメータを受け入れます.このパラメータはキャッシュのキーとして使用されます(デフォルトでは、ページのURLはキャッシュのキーとして使用されます).モデル(model)をパラメータとすると、モデルのcache_keyプロパティはこのkeyとして扱われます.つまり、articleが更新されると、このキャッシュクリップは期限切れになります.コンソール(console)で説明できます.

>> a = Article.first
=> #

>> a.cache_key
=> "articles/1-20090729191417"

cache_keyはモデル名、モデルid、updated_によってat属性組成.keyの最後のセグメントは非常に有用です.このセグメントの構成部分では、このkeyは毎回モデルの更新のために変更される必要があります.これにより、モデルの任意のプロパティが変更されるたびに、このキャッシュクリップは期限切れになります.
私たちはarticleページを2回リフレッシュしてキャッシュを実証します.開発中ロゴには次のようなものがあります.

  Processing ArticlesController#show (for 127.0.0.1 at 2009-07-30 20:22:30) [GET]
    Parameters: {"id"=>"1"}
    Article Load (0.2ms)   SELECT * FROM "articles"WHERE ("articles"."id"= 1)
  Rendering/Users/eifion/rails/apps_for_asciicasts/ep172/app/views/articles/show.html.erb
  Cached fragment hit: views/articles/1-20090729225258 (0.0ms)
    SQL (0.2ms)   SELECT count(*) AS count_all FROM "comments"WHERE ("comments".article_id = 1)
    CACHE (0.0ms)   SELECT count(*) AS count_all FROM "comments"WHERE ("comments".article_id = 1)
    Comment Load (0.3ms)   SELECT * FROM "comments"WHERE ("comments".article_id = 1)
  Cached fragment miss: views/articles/1-20090729225258 (0.0ms)
  Processing ArticlesController#show (for 127.0.0.1 at 2009-07-30 20:22:45) [GET]
    Parameters: {"id"=>"1"}
    Article Load (0.2ms)   SELECT * FROM "articles"WHERE ("articles"."id"= 1)
  Rendering/Users/eifion/rails/apps_for_asciicasts/ep172/app/views/articles/show.html.erb
  Cached fragment hit: views/articles/1-20090729225258 (0.0ms)

最初にページをロードしたとき、キャッシュ内にそのkeyに対応するキャッシュクリップがないため、対応するキャッシュクリップ(cached fragment)が見つかりませんでした.データがデータベースから取り出され、キャッシュが作成されます.2回目のページのロード時にkeyのキャッシュクリップが見つかり、データベースからデータを読み込む必要はありません.
タイトルの変更などarticleを編集すると、このキャッシュクリップは自動的に失効し、ページが更新されます.このときarticleを更新するとモデルのupdated_atプロパティも変更され、モデルのcache_keyもこれに応じて更新されます.
Touchの使用
私たちの今のすべての変更は、初期バージョンのrailsで動作するはずです.ではtouchはどのように働いていますか?touchがコンソールの下でどのように動作するかから始めます.
最初のarticleを取得してupdatedを見つけましたat属性.

>> a = Article.first
=> #

>> a.updated_at
=> Wed, 29 Jul 2009 22:27:34 UTC +00:00

articleに対してtouchメソッドを呼び出すとupdated_at属性も変更されます.

>> a.touch
=> true
>> a.updated_at
=> Wed, 29 Jul 2009 22:27:53 UTC +00:00

これがtouchです.モデルがtouchメソッドを呼び出すと、モデルはupdated_を変更します.at属性値は現在の時間である.これは特に有用な方法ではないように見えますが、associationsで使用するとtouch方法はその価値を示します.
私たちのアプリケーションにはArticleがたくさんあるかもしれません.articleページのフォームを使用してarticleにコメントを追加すると、このコメントはarticleページの一部として表示されません.これはarticleがキャッシュされているため、articleページにはキャッシュ内のcommentsしか表示されません.コメントが追加されるとarticleのタイムスタンプは変更されないため、キャッシュクリップは期限切れになりません.
コメントを追加または変更するときにarticleページに新しいコメントを表示するには、コメントモデル(model)を少し変更する必要があります.

class Comment < ActiveRecord::Base  
  belongs_to :article, :touch => true  
end  

belongs_へto関係追加:touch=>trueは、commentが作成され、更新または削除されると、そのcommentが(belongs_to)に属するarticleがtouchedされることを意味する.次に、キャッシュが無効になり、ページが更新され、追加したばかりのコメントが表示されるコメントを追加します.
この技術は、フラグメントキャッシュ(fragment caching)のみではない.touchもよくMemcachedと動作し、新しいキャッシュが作成されるとMemcachedは古いキャッシュを自動的にクリアします.sweepersを使用する必要はありません.sweepersに必要な余分なコードを書く必要はありません.