# 機能設計書 15-Journey

## 概要

本ドキュメントは、Ruby on Railsフレームワークにおけるルーティングエンジン「Journey」の機能設計を記載する。JourneyはURLパターンマッチングとパス生成を担当するAction Dispatchの内部コンポーネントである。

### 本機能の処理概要

Journeyは、RailsルーティングシステムのコアエンジンであるURLパターンマッチングとパス生成を提供する。受信リクエストのURLを解析して適切なコントローラアクションにマッピングし、逆にコントローラアクションからURLを生成する機能を持つ。

**業務上の目的・背景**：
WebアプリケーションではURLとコントローラアクションの対応付けが必須である。Journeyは、`config/routes.rb`で定義されたルーティング設定をパースして効率的なマッチング構造（有限状態マシン）を構築する。これにより、大量のルート定義があっても高速にマッチングを行い、リクエスト処理のオーバーヘッドを最小化する。また、名前付きルートからのURL生成（`posts_path`等）も効率的に実行できる。

**機能の利用シーン**：
- HTTPリクエストの受信時にコントローラ・アクションを決定
- `*_path`/`*_url`ヘルパーによるURL生成
- `routes.rb`のコンパイルと最適化
- ルーティングエラーの診断
- ルーティング一覧の表示

**主要な処理内容**：
1. ルートパターンのパース（Scanner/Parser）
2. AST（抽象構文木）の構築
3. 有限状態マシン（GTG: Generalized Transition Graph）の構築
4. 受信URLとルートパターンのマッチング
5. パスパラメータの抽出
6. ルートからURLへの生成（Formatter）
7. ルート優先順位の管理

**関連システム・外部連携**：
- Action Dispatch（ルーティングDSL）
- Action Controller（マッチング結果の利用）
- Rack（HTTPリクエストの受け渡し）

**権限による制御**：
- Journey自体には権限制御機能はない
- ルーティングの`constraints`オプションでアクセス制限を設定可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | ルーティング一覧画面 | 主機能 | ルーティングエンジンによるルート情報の解析・抽出 |
| 9 | ルーティングエラー画面 | 主機能 | ルーティングマッチング失敗時の診断情報生成 |
| 16 | ルーティングFSM可視化画面 | 主機能 | ルーティング有限状態マシンの可視化処理 |

## 機能種別

ルーティング / URLマッチング / パス生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path_info | String | Yes | リクエストパス | - |
| request_method | String | Yes | HTTPメソッド | - |
| constraints | Hash | No | ルート制約条件 | - |
| defaults | Hash | No | デフォルトパラメータ | - |

### 入力データソース

- HTTPリクエスト（Rack環境変数）
- `config/routes.rb`のルート定義

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| route | Journey::Route | マッチしたルート |
| path_parameters | Hash | パスから抽出したパラメータ |
| controller | String | コントローラ名 |
| action | String | アクション名 |
| generated_path | String | 生成されたパス |

### 出力先

- ActionDispatch::Request#path_parameters
- ActionDispatch::Request#route

## 処理フロー

### 処理シーケンス

```
1. ルート定義のコンパイル
   └─ Scanner: パターン文字列のトークン化
   └─ Parser: トークンからASTを構築
   └─ GTG Builder: ASTから有限状態マシンを構築

2. URLマッチング
   └─ Router#serve
      └─ Router#recognize
         └─ GTG Simulator: パスをシミュレート
         └─ Route#matches?: 制約条件チェック
         └─ パラメータ抽出

3. URL生成
   └─ Formatter#generate
      └─ ルート検索
      └─ パラメータ埋め込み
      └─ パス文字列生成
```

### フローチャート

```mermaid
flowchart TD
    A[HTTPリクエスト] --> B[Router#serve]
    B --> C[Router#recognize]
    C --> D[GTG Simulator]
    D --> E{パターンマッチ?}
    E -->|No| F[404 Not Found]
    E -->|Yes| G[Route候補取得]
    G --> H{制約条件チェック}
    H -->|Fail| I[次の候補]
    I --> E
    H -->|Pass| J[パラメータ抽出]
    J --> K[path_parameters設定]
    K --> L[route.app.serve]
    L --> M[コントローラ実行]

    N[*_pathヘルパー] --> O[Formatter#generate]
    O --> P[ルート検索]
    P --> Q[パラメータ埋め込み]
    Q --> R[パス文字列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 優先順位 | 先に定義されたルートが優先 | マッチング時 |
| BR-002 | 制約条件 | constraintsを満たさないとマッチしない | constraints設定時 |
| BR-003 | デフォルト値 | パラメータがない場合はdefaultsを使用 | 生成時 |
| BR-004 | アンカーパス | パスが完全一致でマッチ | anchored route |

### 計算ロジック

**パターンマッチング**：
- GTG（Generalized Transition Graph）による効率的なマッチング
- NFA（非決定性有限オートマトン）を使用

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

Journeyはデータベースを操作しない。

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| RoutingError | 例外 | マッチするルートがない | ルート定義を確認 |
| ActionController::UrlGenerationError | 例外 | URL生成に必要なパラメータ不足 | パラメータを確認 |

### リトライ仕様

なし

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

なし

## パフォーマンス要件

- GTGによる効率的なマッチング（O(n)、nはパス長）
- ルート数が増えてもマッチング速度は維持
- 初回コンパイルはアプリケーション起動時に完了

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

- パスパラメータはURLデコード後に処理
- 制約条件（constraints）によるアクセス制御
- 不正なパスパターンの検出

## 備考

- JourneyはRails 3.2以降のルーティングエンジン
- Action Dispatch内部コンポーネントとして実装
- 開発環境では`rails routes`コマンドでルート一覧を確認可能

---

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

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

### 推奨読解順序

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

ルート、パターン、ノードの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | route.rb | `actionpack/lib/action_dispatch/journey/route.rb` | Routeクラスの属性 |
| 1-2 | pattern.rb | `actionpack/lib/action_dispatch/journey/path/pattern.rb` | パターン構造 |
| 1-3 | node.rb | `actionpack/lib/action_dispatch/journey/nodes/node.rb` | ASTノード定義 |

**読解のコツ**: Routeはルート定義、Patternはパスパターン、Nodeはパースされた構文木の要素を表す。

#### Step 2: パース処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | scanner.rb | `actionpack/lib/action_dispatch/journey/scanner.rb` | トークン化処理 |
| 2-2 | parser.rb | `actionpack/lib/action_dispatch/journey/parser.rb` | AST構築処理 |

**主要処理フロー**:
- Scannerでパターン文字列をトークンに分割
- ParserでトークンからASTを構築

#### Step 3: マッチング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | router.rb | `actionpack/lib/action_dispatch/journey/router.rb` | マッチングエントリーポイント |
| 3-2 | builder.rb | `actionpack/lib/action_dispatch/journey/gtg/builder.rb` | GTG構築 |
| 3-3 | simulator.rb | `actionpack/lib/action_dispatch/journey/gtg/simulator.rb` | マッチングシミュレーション |
| 3-4 | transition_table.rb | `actionpack/lib/action_dispatch/journey/gtg/transition_table.rb` | 状態遷移テーブル |

**主要処理フロー**（router.rb）:
- **30-41行目**: `serve`メソッド、マッチングとルート実行
- **43-100行目**: `recognize`メソッド、パターンマッチングとパラメータ抽出
- **111-113行目**: `filter_routes`でGTGシミュレータを使用

#### Step 4: URL生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | formatter.rb | `actionpack/lib/action_dispatch/journey/formatter.rb` | URL生成処理 |

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

```
routes.rb定義
    │
    └─ ActionDispatch::Routing::RouteSet#add_route
           │
           └─ Journey::Routes#add_route
                  │
                  └─ Journey::Route.new
                         │
                         ├─ Journey::Scanner.scan(パターン)
                         │      │
                         │      └─ トークン列生成
                         │
                         └─ Journey::Parser.parse(トークン)
                                │
                                └─ ASTノード生成


HTTPリクエスト
    │
    └─ Journey::Router#serve
           │
           └─ Journey::Router#recognize
                  │
                  ├─ filter_routes (GTG Simulator)
                  │      │
                  │      └─ simulator.memos(path)
                  │             │
                  │             └─ 状態遷移マッチング
                  │
                  ├─ routes.select { |r| r.matches?(req) }
                  │
                  └─ パラメータ抽出
                         │
                         └─ path_parameters設定


url_for / *_path ヘルパー
    │
    └─ Journey::Formatter#generate
           │
           ├─ ルート検索
           │
           └─ パス文字列組み立て
```

### データフロー図

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

routes.rb ───────────▶ Scanner/Parser ────────────▶ AST
                              │
                              ▼
                         GTG Builder ────────────▶ TransitionTable
                                                        │
                                                        ▼
HTTPリクエスト ──────▶ Router#recognize ◀─────── Simulator
     │                        │
     │                        ▼
     │                 Route候補リスト
     │                        │
     │                        ▼
     │               matches? (制約チェック)
     │                        │
     │                        ▼
     └──────────────▶ path_parameters ───────▶ コントローラ


パラメータ ──────────▶ Formatter#generate ──────▶ URL文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| router.rb | `actionpack/lib/action_dispatch/journey/router.rb` | ソース | ルーターメイン |
| routes.rb | `actionpack/lib/action_dispatch/journey/routes.rb` | ソース | ルートコレクション |
| route.rb | `actionpack/lib/action_dispatch/journey/route.rb` | ソース | ルート定義 |
| scanner.rb | `actionpack/lib/action_dispatch/journey/scanner.rb` | ソース | トークナイザー |
| parser.rb | `actionpack/lib/action_dispatch/journey/parser.rb` | ソース | パーサー |
| formatter.rb | `actionpack/lib/action_dispatch/journey/formatter.rb` | ソース | URL生成 |
| visitors.rb | `actionpack/lib/action_dispatch/journey/visitors.rb` | ソース | AST訪問者 |
| pattern.rb | `actionpack/lib/action_dispatch/journey/path/pattern.rb` | ソース | パスパターン |
| node.rb | `actionpack/lib/action_dispatch/journey/nodes/node.rb` | ソース | ASTノード |
| builder.rb | `actionpack/lib/action_dispatch/journey/gtg/builder.rb` | ソース | GTG構築 |
| simulator.rb | `actionpack/lib/action_dispatch/journey/gtg/simulator.rb` | ソース | GTGシミュレータ |
| transition_table.rb | `actionpack/lib/action_dispatch/journey/gtg/transition_table.rb` | ソース | 遷移テーブル |
| dot.rb | `actionpack/lib/action_dispatch/journey/nfa/dot.rb` | ソース | DOT形式出力（可視化） |
| utils.rb | `actionpack/lib/action_dispatch/journey/router/utils.rb` | ソース | ユーティリティ |
