# 画面設計書 14-無効なステートメント画面

## 概要

本ドキュメントは、Ruby on Railsフレームワークにおける「無効なステートメント画面」の設計仕様を定義する。データベース関連のエラー（無効なSQL文、マイグレーション未実行等）が発生した際に表示される開発者向けエラー診断画面である。

### 本画面の処理概要

この画面は、Railsアプリケーションの開発中に、データベース操作で`ActiveRecord::StatementInvalid`例外が発生した際に表示されるエラー診断画面である。SQLシンタックスエラー、テーブル未作成、カラム不足など、データベース関連の問題を診断し、特にAction Text、Active Storage、Action Mailboxなどのコンポーネントが正しくインストールされていない場合には、インストールコマンドを案内する。

**業務上の目的・背景**：Railsアプリケーションでは、マイグレーションの未実行やデータベーススキーマの不整合が頻繁に発生する。特に、Action TextやActive Storageなどの追加コンポーネントを使用する際に、必要なテーブルが作成されていないケースが多い。この画面は、問題の原因を明確にし、適切なインストールコマンドを提示することで、開発者が迅速に問題を解決できるよう支援する。

**画面へのアクセス方法**：開発環境において、データベース操作中に`ActiveRecord::StatementInvalid`が発生した際に、自動的にこの画面が表示される。例えば、マイグレーション未実行状態でテーブルにアクセスした場合、存在しないカラムを参照した場合などに表示される。

**主要な操作・処理内容**：
1. 例外クラス名の表示 - 発生した例外のクラス名（ActiveRecord::StatementInvalid等）を明示
2. コントローラー・アクション情報 - エラー発生元のコントローラーとアクションを表示
3. エラーメッセージの表示 - データベースから返されたエラーメッセージを表示
4. インストール案内 - Action Text、Active Storage、Action Mailbox関連のエラー時にインストールコマンドを案内
5. ソースコード抽出 - エラー発生箇所のソースコードを表示
6. スタックトレースの表示 - Application/Framework/Full Traceの切り替え表示
7. リクエスト・レスポンス情報 - デバッグ用のHTTP情報を表示

**画面遷移**：
- 遷移元：データベース操作エラーが発生したHTTPリクエスト
- 遷移先：なし（エラー画面のため、修正後に再度リクエストを実行）

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | Debug Exceptions | 主機能 | データベース関連エラーの診断情報表示 |
| 3 | Active Record | 補助機能 | SQL文エラー情報の表示 |

## 画面種別

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

## URL/ルーティング

特定のURLは存在しない。データベース操作中にActiveRecord::StatementInvalidが発生した際に、DebugExceptionsミドルウェアが例外を捕捉して本画面を表示する。

例：
- 任意のURLへのリクエスト（DB操作エラー発生時）

## 入出力項目

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

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

## 表示項目

| 項目名 | データ型 | 説明 | ソース |
|--------|----------|------|--------|
| ヘッダータイトル | String | "{例外クラス名} in {Controller}Controller#{action}" | `@exception.class`, `@request.parameters` |
| エラーメッセージ | String | データベースから返されたエラーメッセージ | `@exception.message` |
| Action Text案内 | String | "To resolve this issue run: bin/rails action_text:install" | 条件付き表示 |
| Active Storage案内 | String | "To resolve this issue run: bin/rails active_storage:install" | 条件付き表示 |
| Action Mailbox案内 | String | "To resolve this issue run: bin/rails action_mailbox:install" | 条件付き表示 |
| ソースコード抽出 | Hash | エラー発生行周辺のコード | `@source_extracts` |
| スタックトレース | 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. ユーザーに視覚的フィードバックを表示

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

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

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

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

## メッセージ仕様

| メッセージID | メッセージ種別 | メッセージ内容 | 表示条件 |
|-------------|---------------|---------------|----------|
| MSG-001 | エラー | "{例外クラス名} in {Controller}Controller#{action}" | 常時ヘッダーに表示 |
| MSG-002 | エラー | データベースエラーメッセージ | 常時h2に表示 |
| MSG-003 | 情報 | "To resolve this issue run: bin/rails action_text:install" | action_textテーブル関連エラー時 |
| MSG-004 | 情報 | "To resolve this issue run: bin/rails active_storage:install" | active_storageテーブル関連エラー時 |
| MSG-005 | 情報 | "To resolve this issue run: bin/rails action_mailbox:install" | action_mailboxテーブル関連エラー時 |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|---------|---------|
| ActiveRecord::StatementInvalid | 無効なSQL文の実行、存在しないテーブル/カラムへのアクセス | 本画面を表示（開発環境）/500レスポンス（本番環境） |

## 備考

- エラーメッセージ内に特定のテーブル名が含まれる場合、対応するインストールコマンドが案内される
  - `action_text_rich_texts`テーブル → Action Textインストール案内
  - `active_storage_blobs`または`active_storage_attachments`テーブル → Active Storageインストール案内
  - `action_mailbox_inbound_emails`テーブル → Action Mailboxインストール案内
- HTTPステータスコード500（Internal Server Error）で応答する
- XHRリクエストの場合は、HTMLではなくプレーンテキスト形式でレスポンスを返す

---

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

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

### 推奨読解順序

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

まず、ActiveRecord::StatementInvalidとExceptionWrapperの関係を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | exception_wrapper.rb | `actionpack/lib/action_dispatch/middleware/exception_wrapper.rb` | rescue_templatesで"invalid_statement"へのマッピングを確認 |

**読解のコツ**: 35行目の`ActiveRecord::StatementInvalid`が`invalid_statement`テンプレートにマッピングされていることを確認。

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

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

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

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

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

エラー画面のテンプレートとインストール案内ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | invalid_statement.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.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` | スタックトレース表示 |

**主要処理フロー**:
- **1-8行目（invalid_statement.html.erb）**: ヘッダーで例外クラス名とコントローラー情報を表示
- **12-23行目**: h2でエラーメッセージを表示、Action Text/Active Storage/Action Mailboxのインストール案内を条件分岐
- **14-16行目**: Action Text関連テーブルエラー時のインストール案内
- **17-19行目**: Active Storage関連テーブルエラー時のインストール案内
- **20-22行目**: Action Mailbox関連テーブルエラー時のインストール案内
- **25-27行目**: ソースコード抽出、トレース、リクエスト・レスポンス情報を表示

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

```
HTTPリクエスト
    │
    ├─ DebugExceptions#call（middleware/debug_exceptions.rb:30）
    │      │
    │      ├─ @app.call(env) - 通常のアプリケーション処理
    │      │      │
    │      │      └─ ActiveRecord::StatementInvalid 発生
    │      │             └─ データベースエラーメッセージ
    │      │
    │      ├─ ExceptionWrapper.new（exception_wrapper.rb:51）
    │      │      └─ rescue_template → "invalid_statement"
    │      │
    │      └─ 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/invalid_statement.html.erb
    │                                  │
    │                                  ├─ _copy_button.html.erb
    │                                  ├─ インストール案内判定
    │                                  │      ├─ ActionText定義チェック
    │                                  │      ├─ ActiveStorage定義チェック
    │                                  │      └─ ActionMailbox定義チェック
    │                                  ├─ _source.html.erb
    │                                  ├─ _trace.html.erb
    │                                  └─ _request_and_response.html.erb
    │
    └─ HTTPレスポンス（500 Internal Server Error）
```

### データフロー図

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

HTTPリクエスト ───────▶ データベース操作
                              │
                              ▼
                    ActiveRecord::StatementInvalid
                         - message: "PG::UndefinedTable..."
                              │
                              ▼
                    DebugExceptions
                              │
                              ▼
                    ExceptionWrapper
                         - rescue_template: "invalid_statement"
                         - source_extracts
                         - traces
                              │
                              ▼
                    DebugView
                         - @exception
                         - @request
                         - @source_extracts
                         - @traces
                              │
                              ▼
                    invalid_statement.html.erb
                         │
                         ├─ ActionText.table_name チェック
                         ├─ ActiveStorage.table_name チェック
                         └─ ActionMailbox.table_name チェック
                              │
                              ▼
                    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` | ソース | 例外情報のラッパークラス |
| invalid_statement.html.erb | `actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.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` | テンプレート | エラー画面共通レイアウト |
