Ruby on Rails
キャッシング
サーチ…
ロシアの人形のキャッシング
キャッシュされたフラグメントを他のキャッシュされたフラグメントにネストすることができます。これはRussian doll caching
と呼ばれています。
Russian doll caching
の利点は、単一の製品が更新された場合、外側のフラグメントを再生成するときに、他のすべての内部フラグメントを再利用できることです。
前のセクションで説明したように、キャッシュされたファイルが直接依存するレコードのupdated_at
の値が変更された場合、キャッシュされたファイルは期限切れになります。ただし、これによりフラグメントがネストされたキャッシュは期限切れになりません。
たとえば、次のように表示します。
<% cache product do %>
<%= render product.games %>
<% end %>
このビューをレンダリングします。
<% cache game do %>
<%= render game %>
<% end %>
ゲームの属性が変更された場合、 updated_at
値は現在の時刻に設定され、キャッシュが期限切れになります。
ただし、製品オブジェクトのupdated_at
は変更されないため、キャッシュの有効期限は切れず、アプリは古いデータを処理します。これを修正するために、我々はモデルをタッチメソッドと結びつける:
class Product < ApplicationRecord
has_many :games
end
class Game < ApplicationRecord
belongs_to :product, touch: true
end
SQLキャッシュ
クエリキャッシュは、各クエリによって返された結果セットをキャッシュするRails
機能です。 Rails
がその要求に対して同じクエリを再度検出した場合、データベースに対してクエリを再度実行するのではなく、キャッシュされた結果セットを使用します。
例えば:
class ProductsController < ApplicationController
def index
# Run a find query
@products = Product.all
...
# Run the same query again
@products = Product.all
end
end
同じクエリがデータベースに対して2回目に実行されると、実際にはデータベースにヒットしません。結果がクエリから返された最初のときには、クエリキャッシュ(メモリ内)に格納され、2回目はメモリから取得されます。
ただし、クエリキャッシュはアクションの開始時に作成され、そのアクションの終わりに破棄されるため、アクションの持続時間中のみ持続することに注意することが重要です。より永続的な方法でクエリ結果を保存したい場合は、低レベルのキャッシュで行うことができます。
フラグメントキャッシング
Rails.cache
によって提供されているRails.cacheを使用して、リクエストにまたがってシリアライズ可能なRubyオブジェクトをキャッシュすることができます。
キャッシュから特定のキーの値をフェッチするには、 cache.read
使用しcache.read
。
Rails.cache.read('city')
# => nil
cache.write
を使用して、キャッシュに値を書き込みます。
Rails.cache.write('city', 'Duckburgh')
Rails.cache.read('city')
# => 'Duckburgh'
代わりに、 cache.fetch
を使用してキャッシュから値を読み込み、オプションで値がない場合はデフォルト値を書き込むこともできます。
Rails.cache.fetch('user') do
User.where(:is_awesome => true)
end
渡されたブロックの戻り値は、指定されたキーのキャッシュに割り当てられてから返されます。
キャッシュの有効期限を指定することもできます。
Rails.cache.fetch('user', :expires_in => 30.minutes) do
User.where(:is_awesome => true)
end
ページのキャッシュ
ActionPack page_caching gemを使用して個々のページをキャッシュすることができます。これにより、1つの動的要求の結果が静的HTMLファイルとして格納されます。このファイルは、後続の要求に対する動的要求の代わりに提供されます。 READMEには完全な設定手順が含まれています。設定したら、コントローラーのcaches_page
クラス・メソッドを使用して、アクションの結果をキャッシュします。
class UsersController < ActionController::Base
caches_page :index
end
expire_page
を使用して、保存されたHTMLファイルを削除してキャッシュの有効期限を強制します。
class UsersController < ActionController::Base
caches_page :index
def index
@users = User.all
end
def create
expire_page :action => :index
end
end
expire_page
の構文は、 url_for
およびfriendsの構文を模倣しています。
HTTPキャッシング
Rails> = 3には、HTTPキャッシュ機能が付属しています。これは、 Cache-Control
およびETag
ヘッダーを使用して、クライアントまたは仲介者(CDNなど)がページをキャッシュできる期間を制御します。
コントローラーアクションでは、 expires_in
を使用して、そのアクションのキャッシングの長さを設定します。
def show
@user = User.find params[:id]
expires_in 30.minutes, :public => true
end
expires_now
を使用して、訪問しているクライアントまたは仲介者にキャッシュされたリソースの即時有効期限を強制します。
def show
@users = User.find params[:id]
expires_now if params[:id] == 1
end
アクションキャッシング
ページキャッシュと同様に、アクションキャッシュはページ全体をキャッシュします。違いは、キャッシュが提供される前にフィルタが実行される前に、リクエストがRailsスタックにヒットすることです。それはRailsからactionpack-action_caching gemに抽出されました。
一般的な例は、認証が必要なアクションのキャッシュです。
class SecretIngredientsController < ApplicationController
before_action :authenticate_user!, only: :index, :show
caches_action :index
def index
@secret_ingredients = Recipe.find(params[:recipe_id]).secret_ingredients
end
end
オプションには、 :expires_in
、custom :cache_path
(複数の経路を別々にキャッシュする必要のあるアクション)、および/ :unless
アクションをキャッシュするタイミングを制御し:unless
:if
/ :unless
class RecipesController < ApplicationController
before_action :authenticate_user!, except: :show
caches_page :show
caches_action :archive, expires_in: 1.day
caches_action :index, unless: { request.format.json? }
end
レイアウトに動的コンテンツがある場合は、 layout: false
を渡してアクションコンテンツのみをキャッシュしlayout: false
。