# 機能設計書 22-Page Caching

## 概要

本ドキュメントは、Ruby on Railsのページキャッシュ機能の設計仕様を定義する。ページキャッシュは、アクション全体のレスポンスを静的HTMLファイルとして保存し、Webサーバーから直接配信することで最高のパフォーマンスを実現するキャッシュ機構である。

### 本機能の処理概要

**業務上の目的・背景**：Webアプリケーションにおいて、完全に静的なページや、認証不要で全ユーザーに同じ内容を表示するページは、Railsアプリケーションを経由せずに直接Webサーバーから配信することで、劇的なパフォーマンス向上が可能である。ページキャッシュは、このような「完全静的化可能なページ」を自動的にファイル化し、Webサーバー（nginx、Apache等）から直接配信可能にする機能である。

**機能の利用シーン**：公開ページ（ランディングページ、ヘルプページ、利用規約等）、認証不要のコンテンツページ、更新頻度の低い情報ページなど、パーソナライズが不要なページに使用する。ただし、Rails 4以降はactionpack-page_caching gemとして切り出されている。

**主要な処理内容**：
1. コントローラのアクション実行完了後、レスポンスボディを取得
2. ページパスに基づいて静的HTMLファイルのパスを決定
3. public ディレクトリにHTMLファイルとして保存
4. 次回以降のリクエストはWebサーバーが直接HTMLファイルを配信
5. expire_page でキャッシュファイルを削除

**関連システム・外部連携**：Webサーバー（nginx、Apache）と連携し、静的ファイルの直接配信を実現する。actionpack-page_caching gem として提供される。

**権限による制御**：ページキャッシュは認証・認可の前に配信されるため、認証が必要なページには使用不可。全ユーザーに同一コンテンツを配信する場合のみ使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 静的ページ | 主機能 | caches_pageによるページ全体の静的ファイル化 |

## 機能種別

キャッシュ処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| action | Symbol | Yes | キャッシュ対象のアクション名 | コントローラに定義されたアクション |
| options[:if] | Proc | No | キャッシュ実行条件 | trueを返す場合のみキャッシュ |
| options[:unless] | Proc | No | キャッシュ除外条件 | trueを返す場合はキャッシュしない |
| options[:gzip] | Boolean/Symbol | No | gzip圧縮の有無 | true/:best_compression/:best_speed |

### 入力データソース

- コントローラクラスでのcaches_page宣言
- アクションのレスポンスボディ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cached_page | File | 静的HTMLファイル |
| gzipped_page | File | gzip圧縮されたHTMLファイル（オプション） |

### 出力先

- public ディレクトリ配下の静的HTMLファイル
- 例：`public/products/index.html`

## 処理フロー

### 処理シーケンス

```
1. caches_page 宣言（コントローラクラス定義時）
   └─ after_action コールバックとして登録
2. アクション実行
   └─ 通常のコントローラ処理
3. レスポンス生成後
   └─ cache_page コールバック実行
4. キャッシュファイル生成
   └─ リクエストパスから保存先を決定
   └─ HTMLファイルとして保存
   └─ gzip 圧縮（オプション）
5. 次回リクエスト
   └─ Webサーバーが直接静的ファイルを配信
```

### フローチャート

```mermaid
flowchart TD
    A[caches_page 宣言] --> B[after_action 登録]
    B --> C[アクション実行]
    C --> D[レスポンス生成]
    D --> E{キャッシュ条件?}
    E -->|if: false| F[キャッシュスキップ]
    E -->|条件満たす| G[cache_page 実行]
    G --> H[パス決定]
    H --> I[HTMLファイル保存]
    I --> J{gzip有効?}
    J -->|Yes| K[gzip圧縮ファイル作成]
    J -->|No| L[完了]
    K --> L
    F --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-22-01 | 認証ページ除外 | 認証が必要なページはページキャッシュ不可 | セッションやユーザー情報に依存するページ |
| BR-22-02 | GETリクエスト限定 | GETリクエストのみキャッシュ対象 | POST/PUT/DELETE等は対象外 |
| BR-22-03 | default_static_extension | デフォルト拡張子は .html | 設定で変更可能 |

### 計算ロジック

キャッシュファイルパス計算：
```ruby
page_cache_path = "#{page_cache_directory}/#{request.path}.#{default_static_extension}"
# 例: public/products/123.html
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし（ファイルシステムのみ） |

### テーブル別操作詳細

本機能はデータベースを直接操作しない。public ディレクトリ配下のファイルシステムに対してファイル作成・削除操作を行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Errno::ENOENT | IOError | 保存先ディレクトリが存在しない | ディレクトリを事前作成 |
| Errno::EACCES | PermissionError | ファイル書き込み権限がない | パーミッション設定を確認 |

### リトライ仕様

ファイル書き込み失敗時のリトライは行わない。エラーはログに記録される。

## トランザクション仕様

本機能はデータベーストランザクションを使用しない。ファイルシステム操作のため、アトミック性は保証されない。

## パフォーマンス要件

- キャッシュヒット時：Webサーバーが直接配信（Railsを経由しない）
- 初回リクエスト：通常のRails処理 + ファイル書き込みオーバーヘッド

## セキュリティ考慮事項

- 認証が必要なページには使用しないこと
- ユーザー固有の情報を含むページには使用しないこと
- キャッシュファイルのパーミッションを適切に設定すること
- 秘密情報がキャッシュされないよう注意すること

## 備考

- Rails 4以降はactionpack-page_caching gemとして切り出されている
- 現代のRailsアプリケーションではCDNやリバースプロキシでの同等機能が一般的
- 動的コンテンツには Fragment Caching または HTTP Caching を推奨

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 基本設定を理解する

ページキャッシュの基本設定と有効化方法を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | caching.rb | `actionpack/lib/abstract_controller/caching.rb` | default_static_extensionの設定、perform_caching設定 |

**読解のコツ**: Rails 4以降はactionpack-page_caching gemとして分離されているため、主要な実装はgemを参照する必要がある。

**主要処理フロー**:
- **35-37行目**: default_static_extension設定（デフォルト ".html"）
- **39-41行目**: perform_caching設定

#### Step 2: キャッシュストア基盤を理解する

ページキャッシュが利用するキャッシュ基盤を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cache.rb | `activesupport/lib/active_support/cache.rb` | キャッシュストアの基本インターフェース |

**読解のコツ**: ページキャッシュはキャッシュストアを直接使用せず、ファイルシステムに直接書き込むが、設定の考え方は共通。

### プログラム呼び出し階層図

```
Controller Class Definition
    │
    ├─ caches_page :action (宣言)
    │      └─ after_action :cache_page, only: [:action]
    │
    └─ アクション実行
           │
           └─ after_action コールバック
                  │
                  └─ cache_page メソッド
                         │
                         ├─ page_cache_path 計算
                         │
                         └─ File.write (HTMLファイル保存)
                                │
                                └─ Gzip圧縮（オプション）
```

### データフロー図

```
[入力]                      [処理]                           [出力]

HTTPリクエスト ───▶ Controller#action ───▶ HTMLレスポンス
                           │
                           ▼
                   cache_page コールバック
                           │
                           ▼
                   ファイルパス決定
                   public/{path}.html
                           │
                           ▼
                   ┌─────────────────┐
                   │ ファイルシステム │───▶ public/products/123.html
                   │ (public/)       │───▶ public/products/123.html.gz
                   └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| caching.rb | `actionpack/lib/abstract_controller/caching.rb` | ソース | キャッシュ基本設定 |
| cache.rb | `activesupport/lib/active_support/cache.rb` | ソース | キャッシュストア基盤 |
| page_caching gem | `actionpack-page_caching` | 外部gem | ページキャッシュ実装（Rails 4以降） |
