ActiveSupport::Cache
GitHub概要
スター57,276
ウォッチ2,311
フォーク21,912
作成日:2008年4月11日
言語:Ruby
ライセンス:MIT License
トピックス
activejobactiverecordframeworkhtmlmvcrailsruby
スター履歴
データ取得日時: 2025/8/13 01:43
ライブラリ
ActiveSupport::Cache
概要
ActiveSupport::Cacheは、Ruby on Railsに組み込まれているキャッシングフレームワークです。
詳細
ActiveSupport::Cacheは、Ruby on Railsフレームワークの一部として提供される高機能なキャッシングシステムです。複数のキャッシュストア(メモリ、ファイル、Redis、データベースなど)をサポートし、統一されたAPIを通じてキャッシュ操作を行えます。read、write、delete、exist?、fetchといった基本的なメソッドを提供し、キャッシュキーの自動生成、有効期限の管理、階層的なキャッシュ無効化など高度な機能を備えています。Rails 7以降では、データベースベースのSolid Cacheがデフォルトで利用でき、分散環境でも安定したキャッシングが可能です。フラグメントキャッシュ、SQLクエリキャッシュ、ページキャッシュなど、Webアプリケーションのパフォーマンス向上に必要な機能が包括的に提供されています。
メリット・デメリット
メリット
- 統一されたAPI: 複数のキャッシュストアを同じインターフェースで操作可能
- 豊富なストアオプション: メモリ、ファイル、Redis、データベースなど多様な選択肢
- Rails統合: フレームワークとの深い統合によるシームレスな利用
- 自動キー管理: キャッシュキーの自動生成と衝突回避
- 階層的無効化: 依存関係に基づくキャッシュクリア機能
- 暗号化サポート: セキュアなデータキャッシングが可能
- 分散対応: シャーディング機能による水平スケーリング
デメリット
- Rails依存: Rails以外のプロジェクトでは利用が制限される
- 学習コスト: 設定オプションや最適化技法の習得が必要
- メモリ使用量: 大量のデータをキャッシュする際のメモリ管理が重要
- デバッグの複雑さ: キャッシュ関連の問題の特定が困難な場合がある
- パフォーマンス依存: 不適切な使用でかえってパフォーマンスが低下する可能性
主要リンク
書き方の例
基本的なキャッシュ操作
# キャッシュへの書き込み
Rails.cache.write("user:123", user_data, expires_in: 1.hour)
# キャッシュからの読み込み
cached_user = Rails.cache.read("user:123")
# 存在確認
if Rails.cache.exist?("user:123")
puts "キャッシュが存在します"
end
# キャッシュの削除
Rails.cache.delete("user:123")
fetch メソッドの活用
# キャッシュがあれば取得、なければブロックを実行してキャッシュに保存
user = Rails.cache.fetch("user:#{id}", expires_in: 12.hours) do
User.find(id)
end
# 条件付きキャッシュ
expensive_data = Rails.cache.fetch("calculation:#{params}", expires_in: 1.day) do
# 重い計算処理
perform_expensive_calculation(params)
end
# ネストしたキャッシュキー
Rails.cache.fetch(["user", user.id, "profile", user.updated_at]) do
user.profile_data
end
複数キーの一括操作
# 複数のキャッシュを一度に読み込み
user_ids = [1, 2, 3, 4, 5]
cache_keys = user_ids.map { |id| "user:#{id}" }
cached_users = Rails.cache.read_multi(*cache_keys)
# 複数のキャッシュを一度に書き込み
users_data = {
"user:1" => user1_data,
"user:2" => user2_data,
"user:3" => user3_data
}
Rails.cache.write_multi(users_data, expires_in: 2.hours)
# 複数のキャッシュを一度に削除
Rails.cache.delete_multi("user:1", "user:2", "user:3")
フラグメントキャッシュ
<!-- ERBテンプレートでのフラグメントキャッシュ -->
<% cache ["user_profile", @user, @user.updated_at] do %>
<div class="user-profile">
<h2><%= @user.name %></h2>
<p><%= @user.bio %></p>
<!-- 重い描画処理 -->
</div>
<% end %>
<!-- 条件付きフラグメントキャッシュ -->
<% cache_if @user.cache_enabled?, ["user_data", @user] do %>
<div class="user-data">
<%= render 'expensive_partial' %>
</div>
<% end %>
カスタムキャッシュストアの設定
# config/environments/production.rb
# Redisキャッシュストアの設定
config.cache_store = :redis_cache_store, {
url: ENV['REDIS_URL'],
connect_timeout: 30,
read_timeout: 0.2,
write_timeout: 0.2,
reconnect_attempts: 1,
namespace: 'cache'
}
# ファイルキャッシュストアの設定
config.cache_store = :file_store, '/var/cache/rails', {
namespace: 'app_cache',
expires_in: 1.hour
}
# メモリキャッシュストアの設定(開発環境)
config.cache_store = :memory_store, {
size: 64.megabytes,
namespace: 'development_cache'
}
Solid Cacheの設定と使用
# config/cache.yml
production:
database: cache_production
store_options:
max_age: <%= 2.weeks.to_i %>
max_entries: 1_000_000
namespace: <%= Rails.env %>
encrypt: true
development:
database: cache_development
store_options:
max_size: <%= 256.megabytes %>
namespace: development
# config/environments/production.rb
config.cache_store = :solid_cache_store
# Solid Cache固有の設定
config.solid_cache.size_estimate_samples = 1000
config.solid_cache.encrypt = true
config.solid_cache.key_hash_stage = :indexed
高度なキャッシュパターン
class UserService
def self.fetch_user_with_associations(user_id)
Rails.cache.fetch("user_full:#{user_id}", expires_in: 1.hour) do
User.includes(:profile, :posts, :followers)
.find(user_id)
.as_json(include: [:profile, :posts, :followers])
end
end
def self.invalidate_user_cache(user_id)
# 関連するキャッシュを一括削除
Rails.cache.delete_matched("user*:#{user_id}*")
Rails.cache.delete("user_count")
Rails.cache.delete("recent_users")
end
def self.warm_cache(user_id)
# キャッシュのプリロード
fetch_user_with_associations(user_id)
Rails.cache.fetch("user_stats:#{user_id}", expires_in: 6.hours) do
calculate_user_statistics(user_id)
end
end
end
# モデルでのキャッシュ統合
class User < ApplicationRecord
after_update :expire_cache
after_destroy :expire_cache
def cached_profile
Rails.cache.fetch(cache_key_with_version) do
profile.as_json
end
end
private
def expire_cache
Rails.cache.delete(cache_key_with_version)
Rails.cache.delete_matched("user*:#{id}*")
end
end