# 画面設計書 13-テンプレートエラー画面

## 概要

本ドキュメントは、Ruby on Railsフレームワークにおける「テンプレートエラー画面」の設計仕様を定義する。ERBテンプレートの描画中にエラーが発生した際に表示される開発者向けエラー診断画面である。

### 本画面の処理概要

この画面は、Railsアプリケーションの開発中に、ビューテンプレート（ERB等）の描画処理でエラーが発生した際に表示されるエラー診断画面である。エラー発生箇所のソースコード、行番号、スタックトレースを詳細に表示し、開発者が問題を迅速に特定・修正できるよう支援する。

**業務上の目的・背景**：Railsアプリケーション開発において、ビューテンプレートのシンタックスエラーや実行時エラーは頻繁に発生する。この画面は、エラー発生箇所を視覚的に強調表示し、スタックトレースと併せて問題の原因を明確にすることで、デバッグ時間の短縮に貢献する。特にテンプレート内でRubyコードを実行する際のエラーは、通常のRubyエラーとは異なる行番号管理が必要となるため、専用の画面が用意されている。

**画面へのアクセス方法**：開発環境において、ビューテンプレートの描画中に`ActionView::Template::Error`が発生した際に、自動的にこの画面が表示される。例えば、ERBファイル内で未定義の変数を参照した場合や、メソッド呼び出しエラーが発生した場合に表示される。

**主要な操作・処理内容**：
1. エラー発生箇所の表示 - テンプレートファイル名と行番号を明示
2. エラーメッセージの表示 - 例外のメッセージをコード形式で表示
3. ソースコード抽出 - エラー発生行を中心とした周辺コードをハイライト表示
4. スタックトレースの表示 - Application Trace / Framework Trace / Full Traceの切り替え
5. リクエスト・レスポンス情報の表示 - デバッグ用のHTTP情報を表示
6. クリップボードコピー機能 - エラー情報をクリップボードにコピー

**画面遷移**：
- 遷移元：テンプレート描画中にエラーが発生したHTTPリクエスト
- 遷移先：なし（エラー画面のため、修正後に再度リクエストを実行）

**権限による表示制御**：
- 開発環境（`config.consider_all_requests_local = true`）でのみ詳細情報が表示される
- 本番環境では、この画面は表示されず、`public/500.html`またはカスタムエラーページが表示される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | Debug Exceptions | 主機能 | テンプレート描画エラーの診断情報表示 |
| 5 | Action View | 補助機能 | エラー発生行のソースコード抽出・表示 |

## 画面種別

エラー診断（開発環境専用）

## URL/ルーティング

特定のURLは存在しない。テンプレート描画中にActionView::Template::Errorが発生した際に、DebugExceptionsミドルウェアが例外を捕捉して本画面を表示する。

例：
- 任意のURLへのリクエスト（テンプレート描画エラー発生時）

## 入出力項目

本画面はエラー診断画面のため、ユーザー入力項目は存在しない。

| 項目 | 入出力 | 説明 |
|------|--------|------|
| なし | - | ユーザー入力を受け付けない |

## 表示項目

| 項目名 | データ型 | 説明 | ソース |
|--------|----------|------|--------|
| ヘッダータイトル | String | "{例外名} in {Controller}#{action}" | `@exception_wrapper.exception_name`, `@request.parameters` |
| ファイル名 | String | エラー発生テンプレートファイルのパス | `@exception_wrapper.file_name` |
| 行番号 | Integer | エラー発生行番号 | `@exception_wrapper.line_number` |
| エラーメッセージ | String | 例外のメッセージ | `@exception_wrapper.message` |
| ソースコード抽出 | Hash | エラー発生行周辺のコード | `@source_extracts` |
| サブテンプレートメッセージ | String | パーシャル内でのエラー時の追加情報 | `@exception_wrapper.sub_template_message` |
| スタックトレース | Hash | Application/Framework/Full Trace | `@traces` |
| リクエスト情報 | Hash | HTTPリクエストの詳細 | `@request` |
| レスポンス情報 | Hash | HTTPレスポンスの詳細 | テンプレート内で生成 |
| コピーボタン | HTML | エラー情報をクリップボードにコピー | `_copy_button` パーシャル |

## イベント仕様

### 1-トレースタブ切り替え

**処理内容**：Application Trace / Framework Trace / Full Traceの表示を切り替える。

**トリガー**：トレースタブのクリック

**処理フロー**：
1. ユーザーがタブをクリック
2. JavaScriptが対応するトレースセクションを表示
3. 他のトレースセクションを非表示

**画面遷移**：なし（同一画面内での表示切り替え）

### 2-コピーボタン押下

**処理内容**：画面に表示されているエラー情報をクリップボードにコピーする。

**トリガー**：コピーボタンクリック

**処理フロー**：
1. JavaScriptがエラーメッセージとスタックトレースをテキストとして取得
2. クリップボードにコピー
3. ユーザーに視覚的フィードバックを表示

**画面遷移**：なし（同一画面に留まる）

### 3-ソースコードハイライトクリック

**処理内容**：スタックトレース内の行をクリックすると、対応するソースコード抽出がハイライト表示される。

**トリガー**：トレース行のクリック

**処理フロー**：
1. ユーザーがトレース行をクリック
2. JavaScriptが対応するソースコードセクションにスクロール
3. 該当ソースコードをハイライト

**画面遷移**：なし（同一画面内でのスクロール）

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | なし | なし | 本画面はデータベースへの操作を行わない |

## メッセージ仕様

| メッセージID | メッセージ種別 | メッセージ内容 | 表示条件 |
|-------------|---------------|---------------|----------|
| MSG-001 | エラー | "{例外名} in {Controller}#{action}" | 常時ヘッダーに表示 |
| MSG-002 | 情報 | "Showing {ファイル名} where line #{行番号} raised:" | 常時本文に表示 |
| MSG-003 | エラー | 例外メッセージ | 常時コード表示部に表示 |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|---------|---------|
| ActionView::Template::Error | テンプレート描画中にエラーが発生 | 本画面を表示（開発環境）/500レスポンス（本番環境） |

## 備考

- `ActionView::Template::Error`は元の例外をラップする形で発生し、`cause`属性で元の例外を参照可能
- テンプレートファイル内の行番号はRubyコンパイル後の行番号と異なる場合があるため、ExceptionWrapperが正しい行番号を計算
- パーシャルテンプレート内でエラーが発生した場合、`sub_template_message`でパーシャル名も表示される
- HTTPステータスコード500（Internal Server Error）で応答する

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ActionView::Template::Errorとその関連クラスの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | exception_wrapper.rb | `actionpack/lib/action_dispatch/middleware/exception_wrapper.rb` | ExceptionWrapperクラス、rescue_templates、source_extracts |

**読解のコツ**: 31-38行目の`rescue_templates`で`ActionView::Template::Error`が`template_error`にマッピングされていることを確認。66-67行目の`template_error?`メソッドと70-71行目の`sub_template_message`メソッドを確認。

#### Step 2: エントリーポイントを理解する

処理の起点となるDebugExceptionsミドルウェアを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | debug_exceptions.rb | `actionpack/lib/action_dispatch/middleware/debug_exceptions.rb` | ミドルウェアのcallメソッド、create_template |

**主要処理フロー**:
1. **30-47行目**: `call`メソッドで例外をキャッチ
2. **121-135行目**: `create_template`でDebugViewを作成、source_extractsを渡す
3. **80-95行目**: `render_for_browser_request`でテンプレートをレンダリング

#### Step 3: テンプレート構造を理解する

エラー画面のテンプレートとパーシャルの関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | template_error.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb` | メインテンプレート構造 |
| 3-2 | _source.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_source.html.erb` | ソースコード抽出表示 |
| 3-3 | _trace.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb` | スタックトレース表示 |
| 3-4 | _request_and_response.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb` | リクエスト・レスポンス情報 |

**主要処理フロー**:
- **1-7行目（template_error.html.erb）**: ヘッダーでコントローラー名とアクション名を表示
- **10-13行目**: ファイル名と行番号、エラーメッセージを表示
- **15行目**: `_source`パーシャルでソースコード抽出を表示
- **17行目**: `sub_template_message`でパーシャル情報を表示
- **19-20行目**: `_trace`と`_request_and_response`パーシャルを描画

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

```
HTTPリクエスト
    │
    ├─ DebugExceptions#call（middleware/debug_exceptions.rb:30）
    │      │
    │      ├─ @app.call(env) - 通常のアプリケーション処理
    │      │      │
    │      │      └─ ActionView::Template::Error 発生
    │      │             └─ cause: 元の例外（NameError等）
    │      │
    │      ├─ ExceptionWrapper.new（exception_wrapper.rb:51）
    │      │      ├─ rescue_template → "template_error"
    │      │      ├─ source_extracts
    │      │      ├─ file_name
    │      │      ├─ line_number
    │      │      └─ sub_template_message
    │      │
    │      └─ render_exception（debug_exceptions.rb:58）
    │             │
    │             └─ render_for_browser_request（debug_exceptions.rb:80）
    │                    │
    │                    ├─ create_template（debug_exceptions.rb:121）
    │                    │      └─ DebugView.new
    │                    │
    │                    └─ template.render
    │                           └─ rescues/template_error.html.erb
    │                                  │
    │                                  ├─ _copy_button.html.erb
    │                                  ├─ _source.html.erb
    │                                  ├─ _trace.html.erb
    │                                  └─ _request_and_response.html.erb
    │
    └─ HTTPレスポンス（500 Internal Server Error）
```

### データフロー図

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

HTTPリクエスト ───────▶ ビュー描画処理
                              │
                              ▼
                    ActionView::Template::Error
                         - cause: 元の例外
                         - file_name: エラー発生ファイル
                         - line_number: エラー発生行
                              │
                              ▼
                    DebugExceptions
                              │
                              ▼
                    ExceptionWrapper
                         - source_extracts: ソースコード抽出
                         - traces: スタックトレース
                         - sub_template_message: パーシャル情報
                              │
                              ▼
                    DebugView
                         - @exception_wrapper
                         - @source_extracts
                         - @traces
                              │
                              ▼
                    template_error.html.erb ───────▶ HTMLレスポンス
                                                       (500 Internal Server Error)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| debug_exceptions.rb | `actionpack/lib/action_dispatch/middleware/debug_exceptions.rb` | ソース | 例外捕捉・エラー画面生成ミドルウェア |
| exception_wrapper.rb | `actionpack/lib/action_dispatch/middleware/exception_wrapper.rb` | ソース | 例外情報のラッパークラス |
| template_error.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb` | テンプレート | テンプレートエラー画面のメインテンプレート |
| _source.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_source.html.erb` | テンプレート | ソースコード抽出表示パーシャル |
| _trace.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb` | テンプレート | スタックトレース表示パーシャル |
| _request_and_response.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb` | テンプレート | リクエスト・レスポンス情報パーシャル |
| _copy_button.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb` | テンプレート | コピーボタンパーシャル |
| layout.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb` | テンプレート | エラー画面共通レイアウト |
