# 画面設計書 32-検索画面

## 概要

本ドキュメントは、Fizzyアプリケーションにおける検索画面の設計仕様を記述したものです。

### 本画面の処理概要

検索画面は、カードとコメントを対象とした全文検索機能を提供する画面です。ユーザーが入力した検索クエリに基づいて、アクセス可能なカードとその関連コンテンツを検索し、結果を一覧表示します。

**業務上の目的・背景**：カンバンボードを長期間運用していると、カードの数が増大し、目的のカードを見つけることが困難になります。本画面は、タイトルや本文の全文検索により、ユーザーが素早く目的の情報にアクセスできるようにすることで、業務効率を向上させます。また、カードID（番号）での直接アクセスや、最近の検索履歴からの再検索も可能です。

**画面へのアクセス方法**：ヘッダーの検索アイコンをクリック、またはキーボードショートカットで検索バーを開き、「検索画面を開く」を選択することでアクセスできます。

**主要な操作・処理内容**：
1. 検索クエリ（キーワード）を入力
2. Enterキーで検索を実行
3. 検索結果からカードを選択してカード詳細画面へ遷移
4. 最近の検索履歴から再検索

**画面遷移**：
- 遷移元：ホーム画面（アクティビティ一覧画面）、各種画面のヘッダー検索バー
- 遷移先：カード詳細画面（検索結果クリック時）

**権限による表示制御**：検索結果には、ユーザーがアクセス可能なカード（accessible_cards）のみが表示されます。ボードへのアクセス権がないカードは検索結果に含まれません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | 全文検索 | 主機能 | カードとコメントの全文検索を実行 |
| 54 | 検索クエリ履歴 | 補助機能 | 最近の検索クエリを表示 |

## 画面種別

検索

## URL/ルーティング

- **パス**: `/search`
- **HTTPメソッド**: GET
- **コントローラ**: `SearchesController#show`

## 入出力項目

| 項目名 | 項目ID | 入出力 | データ型 | 必須 | 最大長 | 説明 |
|--------|--------|--------|----------|------|--------|------|
| 検索クエリ | q | 入力 | String | 任意 | 2000 | 検索キーワード |

## 表示項目

| 項目名 | 説明 | データ取得元 |
|--------|------|-------------|
| ページタイトル | 「Search results for "xxx"」または「Search」 | @query |
| 検索フォーム | 検索キーワード入力欄 | - |
| 検索結果一覧 | 検索にマッチしたカードの一覧 | @page.records |
| No matches | 検索結果がない場合のメッセージ | - |
| 最近の検索履歴 | ユーザーの過去の検索クエリ | @recent_search_queries |

## イベント仕様

### 1-検索実行

検索クエリを入力して検索を実行します。

- **トリガー**: Enterキー押下、検索フォーム送信
- **処理フロー**:
  1. 検索クエリを`q`パラメータとしてGETリクエスト送信
  2. `SearchesController#show`で検索処理を実行
  3. カードIDが直接入力された場合は該当カードへリダイレクト
  4. それ以外は全文検索を実行し結果を表示
- **成功時**: 検索結果が一覧表示される
- **結果なし**: 「No matches」メッセージを表示

### 2-カード選択

検索結果からカードを選択します。

- **トリガー**: 検索結果のカードをクリック
- **処理フロー**:
  1. 選択されたカードのIDを取得
  2. カード詳細画面へ遷移
- **遷移先**: `/cards/:id`

### 3-検索クリア

検索フォームをクリアします。

- **トリガー**: クリアボタン（×アイコン）クリック
- **処理フロー**:
  1. Stimulusコントローラ（bar#clearInput）が入力をクリア
  2. 検索結果をリセット

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 検索実行 | search_queries | INSERT/UPDATE | 検索クエリを履歴として保存 |
| 検索実行 | search_records_* | SELECT | 全文検索インデックスを検索 |

### テーブル別更新項目詳細

#### search_queries

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | Current.user.id | 検索実行ユーザー |
| INSERT | terms | 検索クエリ | 最大2000文字 |
| INSERT | account_id | Current.account.id | アカウントID |
| UPDATE | updated_at | 現在時刻 | 既存クエリの場合はtouch |

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|------------|---------------|---------|
| 情報 | no_matches | No matches | 検索結果が0件の場合 |
| ラベル | search_label | Search Fizzy | 検索フォームのラベル |
| プレースホルダー | search_placeholder | Find something... | 検索入力欄のプレースホルダー |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|-----|---------|---------|
| クエリが空 | qパラメータがblank | @queryをnilとし、空の検索結果を表示 |

## 備考

- 全文検索はMySQLのFULLTEXTインデックスを使用
- カードIDを直接入力した場合は、該当カードへ直接リダイレクト
- 検索クエリは履歴として保存され、最近10件まで表示可能
- Turbo Frameを使用した非同期検索結果表示
- search_records_*テーブルはシャーディングされている（0-15）

---

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

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

### 推奨読解順序

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

検索機能のデータモデルと全文検索インデックスの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | searcher.rb | `app/models/user/searcher.rb` | ユーザーの検索機能、search_queriesとの関連 |
| 1-2 | schema.rb | `db/schema.rb` | search_queriesテーブル（444-454行目）、search_records_*テーブル |

**読解のコツ**: `User::Searcher`モジュールは、`search`メソッドで全文検索を実行し、`remember_search`で検索履歴を保存します。search_recordsテーブルはaccount_idでシャーディングされています。

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

コントローラのshowアクションを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | searches_controller.rb | `app/controllers/searches_controller.rb` | showアクションの実装、カードIDによる直接遷移 |

**主要処理フロー**:
1. **5行目**: `@query`に検索クエリを設定（blankならnil）
2. **7-8行目**: カードIDが入力された場合は`@card`を取得してリダイレクト
3. **10行目**: 全文検索を実行して結果をページネーション
4. **11行目**: 最近の検索クエリを10件取得

#### Step 3: ビューレイヤーを理解する

検索画面のテンプレート構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.erb | `app/views/searches/show.html.erb` | 検索画面のメインテンプレート |
| 3-2 | _form.html.erb | `app/views/searches/_form.html.erb` | 検索フォームのパーシャル |
| 3-3 | _results.html.erb | `app/views/searches/_results.html.erb` | 検索結果表示のパーシャル |

**主要処理フロー**:
- **show.html.erb 12行目**: 検索フォームをレンダリング
- **show.html.erb 13-19行目**: Turbo Frameで検索結果を表示
- **show.html.erb 14-15行目**: カードが見つかった場合は自動遷移
- **_form.html.erb**: Stimulusコントローラ（bar）でキーボード操作を制御

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

```
SearchesController#show
    │
    ├─ @query = params[:q]
    │
    ├─ accessible_cards.find_by_id(@query)
    │      │
    │      └─ カードIDの場合 → @card を設定
    │
    ├─ Current.user.search(@query)
    │      │
    │      └─ User::Searcher#search
    │             │
    │             └─ Search::Record.for(account_id).search(terms, user: self)
    │
    ├─ set_page_and_extract_portion_from (ページネーション)
    │
    └─ search_queries.order(updated_at: :desc).limit(10)
           │
           └─ @recent_search_queries
```

### データフロー図

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

検索クエリ               SearchesController#show
  q ─────────────────────▶ カードID判定
                              │
                        ┌─────┴─────┐
                        │           │
                   カードID     検索クエリ
                        │           │
                        ▼           ▼
                   @card取得    全文検索実行
                        │           │
                        ▼           ▼
               カード詳細へ    @page.records ───▶ 検索結果一覧
               リダイレクト

                          search_queries更新
                              │
                              ▼
                        検索履歴保存
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| searches_controller.rb | `app/controllers/searches_controller.rb` | コントローラ | 検索処理の制御 |
| show.html.erb | `app/views/searches/show.html.erb` | テンプレート | 検索画面のメイン表示 |
| _form.html.erb | `app/views/searches/_form.html.erb` | パーシャル | 検索フォーム |
| _results.html.erb | `app/views/searches/_results.html.erb` | パーシャル | 検索結果表示 |
| searcher.rb | `app/models/user/searcher.rb` | コンサーン | ユーザーの検索機能 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（123行目） |
| schema.rb | `db/schema.rb` | スキーマ | search_queries、search_records_*テーブル定義 |
