# 機能設計書 41-タグ一覧表示

## 概要

本ドキュメントは、アカウント内のタグ一覧を表示する機能の設計を定義するものである。

### 本機能の処理概要

**業務上の目的・背景**：カンバンボードシステムにおいて、タグはカードを分類・整理するための重要な機能である。タグ一覧表示機能は、アカウント内で使用されているすべてのタグを一覧化し、各タグに紐づくカードを確認できるようにすることで、タグの管理・整理を効率化する。また、未使用のタグを特定し、削除することでタグの肥大化を防ぐ役割も担う。

**機能の利用シーン**：
- タグの整理・管理を行いたいとき
- 特定のタグがどのカードに使用されているか確認したいとき
- 未使用のタグを削除してタグリストを整理したいとき
- 全体的なタグの使用状況を把握したいとき

**主要な処理内容**：
1. 現在のアカウントに紐づくタグをアルファベット順で取得する
2. ページネーション処理を適用してタグ一覧を分割表示する
3. 各タグに紐づくカード情報を取得して表示する
4. タグ削除機能をUIに提供する

**関連システム・外部連携**：特になし（内部処理のみ）

**権限による制御**：認証済みユーザーであれば、自身のアカウント内のタグ一覧を閲覧可能。他アカウントのタグは参照不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 59 | タグ一覧画面 | 主機能 | すべてのタグと関連カードを一覧表示 |
| 74 | タグ検索プロンプト画面 | 参照画面 | タグ検索用のオートコンプリートプロンプト |

## 機能種別

参照処理（Read）/ 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| page | Integer | No | 表示するページ番号 | 正の整数 |

### 入力データソース

- セッション情報から現在のアカウント（`Current.account`）を取得
- DBのtagsテーブルから該当アカウントのタグを取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tags | Array<Tag> | タグオブジェクトの配列 |
| tag.title | String | タグの名称 |
| tag.cards | Array<Card> | タグに紐づくカードの配列 |

### 出力先

画面表示（HTMLレンダリング）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ GET /tags へのリクエストを受信

2. 認証確認
   └─ ApplicationControllerの認証フィルターで認証状態を確認

3. タグ一覧取得
   └─ Current.account.tags.alphabetically でタグをアルファベット順に取得

4. ページネーション処理
   └─ set_page_and_extract_portion_from メソッドでページング処理

5. ビューレンダリング
   └─ tags/index.html.erb でHTMLを生成して返却
```

### フローチャート

```mermaid
flowchart TD
    A[GET /tags リクエスト] --> B{認証済み?}
    B -->|No| C[ログイン画面へリダイレクト]
    B -->|Yes| D[Current.accountからタグ取得]
    D --> E[アルファベット順でソート]
    E --> F[ページネーション処理]
    F --> G[ビューレンダリング]
    G --> H[HTML返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | アカウントスコープ | タグは所属するアカウント内でのみ表示される | 常時 |
| BR-41-02 | ソート順 | タグはアルファベット順（大文字小文字無視）で表示される | 常時 |
| BR-41-03 | タグ名正規化 | タグ名は小文字に正規化されて保存される | タグ作成時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| タグ一覧取得 | tags | SELECT | アカウントに紐づくタグを取得 |
| カード情報取得 | cards | SELECT | タグに紐づくカードを取得 |
| タグ-カード関連取得 | taggings | SELECT | タグとカードの関連を取得 |

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

#### tags

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, account_id, title, created_at, updated_at | WHERE account_id = Current.account.id ORDER BY lower(title) | アルファベット順 |

#### taggings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | tag_id, card_id | tag.cardsの関連取得時 | has_many :cards, through: :taggings |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | 未認証状態でアクセス | ログイン画面へリダイレクト |

### リトライ仕様

特になし

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

読み取り専用のため、トランザクション管理は不要

## パフォーマンス要件

- 一覧表示のレスポンス時間: 500ms以内
- ページネーションによりデータ量を制御

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

- 認証必須: ログイン済みユーザーのみアクセス可能
- アカウント分離: Current.accountによりマルチテナント分離を実現
- XSS対策: タグ名表示時にエスケープ処理

## 備考

- タグ名は `#` で始めることができない（バリデーション: `format: { without: /\A#/ }`）
- `hashtag` メソッドでタグ名の先頭に `#` を付与した形式を取得可能

---

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

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

### 推奨読解順序

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

まず、タグのデータ構造とリレーションを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tag.rb | `app/models/tag.rb` | Tagモデルの定義、関連、スコープ、バリデーションを確認 |
| 1-2 | tagging.rb | `app/models/tagging.rb` | TagとCardの中間テーブルモデルを確認 |
| 1-3 | schema.rb | `db/schema.rb` | tags, taggingsテーブルの構造を確認（757-763行目、746-755行目） |

**読解のコツ**: Railsのhas_many :through関連により、TagモデルからCardモデルへの参照が可能になっている。`belongs_to :account, default: -> { Current.account }` はマルチテナント対応のパターン。

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

処理の起点となるコントローラーを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tags_controller.rb | `app/controllers/tags_controller.rb` | indexアクションの実装を確認 |
| 2-2 | routes.rb | `config/routes.rb` | ルーティング定義（105行目） |

**主要処理フロー**:
1. **3行目**: `set_page_and_extract_portion_from Current.account.tags.alphabetically` でタグ一覧をページング付きで取得

#### Step 3: ビューレンダリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.erb | `app/views/tags/index.html.erb` | タグ一覧の表示ロジック |

**主要処理フロー**:
- **4-19行目**: 各タグをループして表示
- **7行目**: タグのタイトルを表示
- **11行目**: 関連するカードのタイトルを表示（`tag.cards.pluck(:title).to_sentence`）
- **14-17行目**: タグ削除ボタン

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

```
TagsController#index
    │
    ├─ Current.account.tags
    │      └─ Tag.alphabetically (scope)
    │             └─ order("lower(title)")
    │
    └─ set_page_and_extract_portion_from
           └─ ページネーション処理
```

### データフロー図

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

HTTPリクエスト ───▶ TagsController#index ───▶ @tags
(GET /tags)              │
                         ├─▶ Current.account
                         │      └─▶ tags (has_many)
                         │             └─▶ alphabetically
                         │
                         └─▶ set_page_and_extract_portion_from
                                    │
                                    ▼
                              index.html.erb ───▶ HTML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tags_controller.rb | `app/controllers/tags_controller.rb` | コントローラー | タグ一覧表示のメイン処理 |
| tag.rb | `app/models/tag.rb` | モデル | タグのデータモデル定義 |
| tagging.rb | `app/models/tagging.rb` | モデル | タグとカードの関連モデル |
| index.html.erb | `app/views/tags/index.html.erb` | ビュー | タグ一覧画面のテンプレート |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | スキーマ | データベース構造定義 |
