コレクションキャッシュでキャッシュストアのデフォルト有効期限を保持するよう修正

rails/rails

この修正により、ActionView::PartialRendererのコレクションキャッシュが、expires_in未指定時にキャッシュストアのデフォルト有効期限を上書きしてしまうリグレッションが解消されました。cached: trueのような簡潔な指定でも、キャッシュストアの設定が意図通りに機能するようになります。

背景

#51579でコレクションキャッシュにexpires_inオプションのサポートが追加された際、意図しないリグレッションが発生していました。cached: trueのようにexpires_inを明示しない場合でも、write_multiメソッドにexpires_in: nilが渡されるようになり、キャッシュストアのデフォルト有効期限が無効化されていました。

#56890で報告されたこの問題により、ActionView::PartialRenderer.collection_cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.hour)のようにキャッシュストアのデフォルト有効期限を設定していても、コレクションキャッシュではその設定が無視されていました。一方で、cached: { expires_in: nil }のように明示的に無期限を指定するケースも想定されるため、両者を区別する必要がありました。

技術的な変更

actionview/lib/action_view/renderer/partial_renderer/collection_caching.rbfetch_or_cache_partialメソッドが修正され、expires_inが明示的に指定された場合のみwrite_multiに渡されるようになりました。

変更前:

unless entries_to_write.empty?
  expires_in = @options[:cached][:expires_in] if @options[:cached].is_a?(Hash)
  collection_cache.write_multi(entries_to_write, expires_in: expires_in)
end

変更後:

unless entries_to_write.empty?
  if @options[:cached].is_a?(Hash) && @options[:cached].key?(:expires_in)
    collection_cache.write_multi(entries_to_write, expires_in: @options[:cached][:expires_in])
  else
    collection_cache.write_multi(entries_to_write)
  end
end

@options[:cached].key?(:expires_in)による判定が追加され、expires_inキーの存在を明示的にチェックするようになりました。キーが存在しない場合はwrite_multiexpires_in引数を渡さないため、キャッシュストアのデフォルト設定が適用されます。キーが存在する場合は、その値(nilを含む)がそのまま渡されます。

テストケースも2つ追加されています。1つ目はcached: { expires_in: nil }と明示した場合に無期限キャッシュとなることを検証し、2つ目はcached: trueの場合にキャッシュストアのデフォルト有効期限(1時間)が適用されることを検証しています。

設計判断

キーの存在チェックによるexpires_inの扱いの分岐が採用されました。

単純な値のチェック(if expires_in)ではなく、key?メソッドによるキーの存在確認を使用することで、expires_in: nilという明示的な指定と、expires_inの省略を区別できます。これにより、「デフォルト設定を使いたい」という暗黙の意図と、「明示的に無期限にしたい」という明示的な意図の両方をサポートできます。

メソッド呼び出しの引数リストを分岐させる実装により、Rubyのキーワード引数の仕組みを活用しています。expires_inキーワードが存在しない場合、write_multiは自身のデフォルト動作(キャッシュストアの設定を使用)に従います。

まとめ

本PRは、コレクションキャッシュのオプション処理において、明示的な指定の有無を正確に判定するよう改善した変更です。キーの存在チェックという小さな修正により、キャッシュストアのデフォルト設定の活用と、明示的な有効期限の指定という2つのユースケースを両立させています。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術・設計(各論)→まとめ(結論)という「総論→各論→結論」の構成が明確に適用されており、すべての必須要素が過不足なく含まれています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```ruby:ファイルパス)の形式、およびIssue/PR番号のリンク記法([#123](URL))は正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

リグレッション、キャッシュストア、`write_multi`といった用語を前提としており、専門知識を持つエンジニアという対象読者に完全に適合しています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクション、各パラグラフが「総論→各論」の構造で書かれており、トピックセンテンスが先頭に配置されているため、非常に読みやすい構成です。1段落1トピックの原則も守られています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内の変更前後のコードブロックは、提供されたDiff情報と完全に一致しています。ファイルパスも正確です。また、追加されたテストケースに関する言及もDiffの内容と整合性が取れています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`ActionView::PartialRenderer`、`expires_in`、`write_multi`、`リグレッション`などの技術用語が、PRの文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

「`key?`でキーの存在をチェックし、存在しない場合は`expires_in`引数を渡さないことでキャッシュストアのデフォルト設定を活かす」という説明は、コード変更の意図と実装を技術的に正しく解説しています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

リグレッションの原因となったPR番号(#51579)や報告されたIssue番号(#56890)など、記事内のすべての主張がPRのDescriptionやDiff内のコードで裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#56891, #51579)やIssue番号(#56890)などの数値や固有名詞は、すべて元のPR情報と正確に一致しています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「コレクションキャッシュでキャッシュストアのデフォルト有効期限を保持するよう修正」は、元のPRタイトル「Fix collection caching to preserve store default expires_in」を正確に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事は提供されたPR情報(Description, Diff)のみに基づいており、バージョンのサポート状況やリリース日程といったPR外の知識の追記や捏造はありません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「リグレッションが発生していました」「解消されました」といった時間表現は、PRの文脈(過去の問題とその修正)を正しく反映しており、歪曲はありません。