💾
汎用ページキャッシュ機能を作ってみた(Ruby on Rails)
Railsのページキャッシュとして有名な gem actionpack-page_caching
。
しかし、これはRails的には非推奨らしいので、似たような汎用ページキャッシュ機能を自作してみました。
コード
# frozen_string_literal: true
module PageCacheable
extend ActiveSupport::Concern
included do
before_action :cache_enabled?, if: -> { action_exists? }
end
# ページキャッシュの保存先を指定
PAGE_CACHE_DIR = Rails.root.join("public", "page_cache")
# キャッシュ時間を設定
CACHE_EXPIRATION_TIME = 1.minutes
private
def action_exists?
respond_to?(action_name)
end
def cache_enabled?
return false if Rails.env.development?
return false unless cache_valid?
render(layout: false, file: cache_path) and return false
end
def cache_valid?
return false unless File.exist?(cache_path)
cache_created_at = File.mtime(cache_path)
Time.now < cache_created_at + CACHE_EXPIRATION_TIME
end
def cache_path
param_key = params_to_cache_key(params)
"#{Rails.root.join(PAGE_CACHE_DIR, controller_name, action_name, param_key)}.html"
end
def params_to_cache_key(params)
# permitの値はキャッシュしたいパターンに応じて調整
safe_params = params.permit(:id, :page)
safe_params.to_h.sort.to_h.to_s.parameterize
end
def render_cache_page(view)
response_body = render(view)
FileUtils.mkdir_p(File.dirname(cache_path))
File.write(cache_path, response_body)
end
def clear_cache(path = cache_path)
cache_file = path
FileUtils.rm_f(cache_file)
end
end
使い方
class ArticlesController < ApplicationController
# 使いたいcontrollerでinclude(ApplicationControllerでincludeしても良い)
include PageCacheable
def show
# 既存のページキャッシュを削除したい場合
clear_cache if hoge_fuga?
# 返すviewを明示的に指定
render_cache_page(:show)
end
end
使いたい人はコピペしてどうぞ。
Discussion