# 機能設計書 12-カラム一覧表示

## 概要

本ドキュメントは、ボード内のカラム一覧を表示する機能の設計を記載する。

### 本機能の処理概要

本機能は、カンバンボードに設定されたカラム（列）の一覧を取得し、画面に表示する機能である。カラムはボード内でカードを分類・整理するための基本単位であり、「To Do」「In Progress」「Done」といったステータスや、プロジェクトのフェーズを表現するために使用される。

**業務上の目的・背景**：カンバンボードでは、タスクの進捗状況をカラムによって視覚的に管理する。ユーザーがボードを開いた際に、どのようなカラム構成になっているかを即座に把握できる必要がある。また、各カラム内のカードを効率的に閲覧するため、カラム単位でのフィルタリングやページネーションにも対応する。

**機能の利用シーン**：ボード詳細画面を表示する際にカラム一覧が読み込まれる。また、特定のカラムを選択してそのカラム内のカードのみを表示する画面（カラム詳細画面）も提供される。

**主要な処理内容**：
1. ボード内の全カラムをposition順にソートして取得（index）
2. 特定カラムの詳細とそのカラム内のカードを取得（show）
3. ETags を使用したHTTPキャッシュによるパフォーマンス最適化

**関連システム・外部連携**：ETags（fresh_when）を使用してブラウザキャッシュを活用。Turbo Framesによる部分更新に対応。

**権限による制御**：ユーザーがアクセス可能なボードに属するカラムのみ取得可能。BoardScopedにより認証・認可を実施。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | ボード詳細画面 | 主画面 | ボード内のカラム一覧を表示 |
| 13 | ボードカラム詳細画面 | 主画面 | 特定カラムの詳細とカードを表示 |
| 14 | ストリームカラム画面 | 参照画面 | ストリームカラムのカード一覧を表示 |
| 15 | Not Nowカラム画面 | 参照画面 | Not Nowカラムのカード一覧を表示 |
| 16 | クローズドカラム画面 | 参照画面 | クローズされたカラムのカード一覧を表示 |

## 機能種別

CRUD操作（Read） / データ取得処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| board_id | UUID | Yes | 対象ボードのID | 存在するボードであること、ユーザーがアクセス可能であること |
| id | UUID | No (showのみ必須) | 対象カラムのID | 該当ボードに属するカラムであること |

### 入力データソース

- URLパラメータ: board_id、id（カラムID）
- セッション: 認証済みユーザー情報（Current.user）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| columns | Array[Column] | カラムオブジェクトの配列（position昇順） |
| column.id | UUID | カラムのID |
| column.name | String | カラム名（最大255文字） |
| column.color | String | カラムの表示色 |
| column.position | Integer | 表示順序 |
| cards | Array[Card] | カラム内のカード一覧（showアクション時） |

### 出力先

- 画面表示: HTML/Turbo Frames
- HTTPヘッダー: ETag（キャッシュ用）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信（GET /boards/:board_id/columns または GET /boards/:board_id/columns/:id）
   └─ BoardScopedによりboard_idからボードを取得

2. カラムデータ取得
   └─ index: @board.columns.sorted で全カラムを取得
   └─ show: @board.columns.find(params[:id]) で特定カラムを取得

3. キャッシュチェック（fresh_when）
   └─ ETagが一致すれば304 Not Modifiedを返す

4. showの場合はカード一覧を取得
   └─ @column.cards.active.latest.with_golden_first.preloaded でページネーション

5. レスポンス生成
   └─ HTML: ビューをレンダリング
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{アクション種別}
    B -->|GET index| C[BoardScoped: ボード取得]
    B -->|GET show| C
    C --> D{アクション}
    D -->|index| E[columns.sorted取得]
    D -->|show| F[columns.find取得]
    E --> G[fresh_when ETag]
    F --> H[カード一覧取得]
    H --> I[fresh_when ETag]
    G --> J{キャッシュ有効?}
    I --> J
    J -->|Yes| K[304 Not Modified]
    J -->|No| L[ビューレンダリング]
    K --> M[終了]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | position順ソート | カラムはposition値の昇順で表示される | index取得時 |
| BR-02 | アクティブカードのみ | show時はactive（公開済み）カードのみ表示 | show取得時 |
| BR-03 | ゴールデンカード優先 | ゴールデンマーク付きカードが先頭に表示 | show取得時 |
| BR-04 | 最新順ソート | カード一覧はlast_active_at降順でソート | show取得時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| index | columns | SELECT | position順でカラム一覧取得 |
| show | columns | SELECT | IDでカラム1件取得 |
| show | cards | SELECT | カラムに属するカード一覧取得 |

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

#### columns

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | board_id = @board.id | 全カラム |
| SELECT | * | id = params[:id], board_id = @board.id | 特定カラム |

#### cards（showアクション時）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | column_id = @column.id, status = 'published' | activeスコープ |
| ORDER BY | last_active_at, goldness | DESC | latest + with_golden_first |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 存在しないboard_idまたはcolumn_idが指定 | RecordNotFound例外 |
| 401 | Unauthorized | 未認証ユーザーがアクセス | ログイン画面へリダイレクト |

### リトライ仕様

該当なし（読み取り専用操作）

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

該当なし（SELECT文のみ）

## パフォーマンス要件

- レスポンス時間: 100ms以内
- ETagによるキャッシュでネットワーク帯域を削減
- preloadedスコープで関連データをN+1なく取得

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

- 認証: ログイン済みユーザーのみアクセス可能
- 認可: BoardScopedによりCurrent.user.boardsでアクセス可能なボードのみ

## 備考

- カラム一覧はボード詳細画面の一部として表示されることが多い
- ストリーム、Not Now、クローズドは特殊カラムとして別コントローラーで処理

---

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

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

### 推奨読解順序

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

カラムのデータ構造とソート機能を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | column.rb | `app/models/column.rb` | カラムモデルの基本構造。Positioned concernをinclude |
| 1-2 | positioned.rb | `app/models/column/positioned.rb` | sortedスコープの定義（position昇順） |

**読解のコツ**: Railsのscope機能により、`columns.sorted`と呼ぶだけでposition順にソートされたコレクションが得られる。

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

リクエストを受け付けるコントローラーを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | columns_controller.rb | `app/controllers/boards/columns_controller.rb` | index/showアクションの実装 |
| 2-2 | board_scoped.rb | `app/controllers/concerns/board_scoped.rb` | ボードの取得処理 |

**主要処理フロー**:
1. **6-9行目**: indexアクションで@board.columns.sortedを取得しfresh_whenでETag設定
2. **11-14行目**: showアクションでカード一覧をページネーション付きで取得
3. **44-46行目**: set_columnでparams[:id]からカラムを取得

#### Step 3: ビュー表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.erb | `app/views/boards/columns/show.html.erb` | カラム詳細とカード一覧の表示 |

**主要処理フロー**:
- **14-24行目**: Turbo Frameでカード一覧をラップし、ページネーション対応
- **18行目**: cards/display/previewsパーシャルでカードを表示

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

```
Boards::ColumnsController
    │
    ├─ BoardScoped (concern)
    │      └─ set_board (Current.user.boards.find)
    │
    ├─ index
    │      └─ @board.columns.sorted
    │             └─ Column::Positioned.sorted (scope)
    │
    └─ show
           ├─ set_column (@board.columns.find)
           └─ @column.cards.active.latest.with_golden_first.preloaded
                  └─ Card scopes (active, latest, etc.)
```

### データフロー図

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

GET /boards/:board_id/columns
         │
         ▼
┌─────────────────┐
│ board_id取得     │ ───▶ Current.user.boards.find
└─────────────────┘
         │
         ▼
┌─────────────────┐
│ columns.sorted  │ ───▶ columns (SELECT)
└─────────────────┘
         │
         ▼
┌─────────────────┐
│ fresh_when      │ ───▶ ETag生成/比較
└─────────────────┘
         │
         ▼
┌─────────────────┐
│ ビューレンダリング │ ───▶ HTML/Turbo Frames
└─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| columns_controller.rb | `app/controllers/boards/columns_controller.rb` | コントローラー | カラム一覧・詳細のリクエスト処理 |
| board_scoped.rb | `app/controllers/concerns/board_scoped.rb` | concern | ボード取得 |
| column.rb | `app/models/column.rb` | モデル | カラムモデル |
| positioned.rb | `app/models/column/positioned.rb` | concern | position管理とソート |
| show.html.erb | `app/views/boards/columns/show.html.erb` | ビュー | カラム詳細表示 |
| schema.rb | `db/schema.rb` | スキーマ | columnsテーブル定義（239-249行目） |
