# 画面設計書 21-スニペット探索

## 概要

本ドキュメントは、GitLabのスニペット探索画面に関する設計書である。この画面はGitLab内で公開されているスニペットを探索・閲覧するための画面であり、ユーザーがコード片やテキストの共有リソースを発見するための主要な入口となる。

### 本画面の処理概要

スニペット探索画面は、GitLabインスタンス内で公開されているスニペットを一覧表示し、ユーザーが目的のスニペットを効率的に見つけることができる機能を提供する。

**業務上の目的・背景**：スニペットは、コード片や設定ファイル、メモなどを共有するための機能である。開発チーム間でよく使用されるコードパターンやスクリプトを共有する際に活用される。この探索画面により、ユーザーは他のユーザーが公開したスニペットを発見し、再利用することができる。これにより、知識の共有促進と開発効率の向上が期待できる。

**画面へのアクセス方法**：
- サイドバーの「Explore」メニューから「Snippets」を選択
- 直接URL `/explore/snippets` にアクセス

**主要な操作・処理内容**：
1. 公開スニペットの一覧表示 - 組織内の公開スニペットをページネーション付きで表示
2. スニペット詳細への遷移 - 一覧から特定のスニペットを選択して詳細画面へ移動
3. 新規スニペット作成への遷移 - 権限がある場合、新規スニペット作成ボタンから作成画面へ移動
4. プロジェクトへのリンク - スニペットが所属するプロジェクトへの遷移

**画面遷移**：
- 遷移元：ダッシュボード、サイドナビゲーション、ダイレクトURL
- 遷移先：スニペット詳細画面、スニペット新規作成画面、プロジェクト詳細画面

**権限による表示制御**：
- 未ログインユーザー：公開スニペットの閲覧のみ可能
- ログインユーザー：公開スニペットの閲覧、新規スニペット作成ボタンの表示（`create_snippet`権限がある場合）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 72 | 個人スニペット | 主機能 | 公開スニペットの探索 |

## 画面種別

一覧

## URL/ルーティング

- URL: `/explore/snippets`
- ルーティング: `config/routes/explore.rb` - `resources :snippets, only: [:index]`
- コントローラ: `Explore::SnippetsController#index`

## 入出力項目

| 項目名 | 入力/出力 | 必須 | データ型 | 説明 |
|--------|----------|------|----------|------|
| page | 入力 | - | Integer | ページネーションのページ番号 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| スニペットタイトル | String | スニペットのタイトル |
| スニペット作成者 | User | スニペットを作成したユーザー |
| 作成日時 | DateTime | スニペットの作成日時 |
| 可視性 | String | public/internal/private |
| コメント数 | Integer | スニペットに対するコメント数 |
| プロジェクト名 | String | 所属プロジェクト（存在する場合） |
| スニペット統計 | Object | リポジトリサイズ等の統計情報 |

## イベント仕様

### 1-ページ読み込み

1. `Explore::SnippetsController#index` が呼び出される
2. `SnippetsFinder` を使用して公開スニペットを検索
3. ページネーション処理を適用
4. スニペット一覧をビューに渡してレンダリング

### 2-新規スニペット作成ボタン押下

- 権限チェック: `can?(current_user, :create_snippet)`
- 遷移先: `/snippets/new`

### 3-スニペット選択

- 遷移先: `/snippets/:id` または `/:namespace/:project/-/snippets/:id`

### 4-ページネーション

- 次/前ページのリンクをクリック
- `page` パラメータを更新してリロード

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ読み込み | snippets | SELECT | 公開スニペットの一覧取得 |
| ページ読み込み | users | SELECT | スニペット作成者情報の取得 |
| ページ読み込み | snippet_statistics | SELECT | スニペット統計情報の取得 |

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

#### snippets

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | visibility_level = public AND organization_id = current_organization.id | 公開スニペットのみ |

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|------------|--------------|---------|
| 情報 | SnippetsEmptyState | There are no snippets found | スニペットが0件の場合 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| 組織が存在しない場合 | 空のスニペット一覧を表示 |
| ページ番号が範囲外 | 空の結果を表示 |

## 備考

- 探索画面は組織（Organization）スコープでフィルタリングされる
- ページネーションは `without_count` を使用しており、総件数は表示されない

---

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

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

### 推奨読解順序

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

スニペットのデータモデルと関連するファインダーの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | snippet.rb | `app/models/snippet.rb` | Snippetモデルの構造、スコープ、バリデーション |
| 1-2 | snippets_finder.rb | `app/finders/snippets_finder.rb` | スニペット検索ロジック、フィルタリング条件 |

**読解のコツ**: SnippetsFinderの`execute`メソッドで、`explore: true`オプションが渡された場合の挙動を確認する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | snippets_controller.rb | `app/controllers/explore/snippets_controller.rb` | コントローラのindexアクション |

**主要処理フロー**:
1. **9行目**: `SnippetsFinder.new(current_user, organization_id: Current.organization.id, explore: true)` - ファインダーの初期化
2. **10行目**: `.execute` - スニペット検索の実行
3. **11-14行目**: ページネーション、関連データのプリロード
4. **16行目**: `noteable_meta_data` - コメント数等のメタデータ取得

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.haml | `app/views/explore/snippets/index.html.haml` | メインビューのレイアウト |
| 3-2 | _list.html.haml | `app/views/shared/snippets/_list.html.haml` | スニペット一覧のパーシャル |
| 3-3 | _snippet.html.haml | `app/views/shared/snippets/_snippet.html.haml` | 個別スニペット表示のパーシャル |

**主要処理フロー**:
- **8-10行目（index.html.haml）**: 新規作成ボタンの権限チェックと表示
- **12行目（index.html.haml）**: 共有パーシャルを使用したスニペット一覧表示

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

```
Explore::SnippetsController#index
    │
    ├─ SnippetsFinder.new
    │      └─ #execute
    │            ├─ filter_by_organization
    │            ├─ filter_by_visibility
    │            └─ apply_explore_filter
    │
    ├─ Kaminari.paginate
    │
    └─ noteable_meta_data
           └─ Gitlab::NoteableMetadata
```

### データフロー図

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

リクエスト ───▶ SnippetsController#index ───▶ @snippets
    │                     │
    │                     ├─ SnippetsFinder ───▶ 検索結果
    │                     │
    │                     ├─ ページネーション ───▶ ページ分割結果
    │                     │
    │                     └─ メタデータ取得 ───▶ @noteable_meta_data
    │
    └─────────────────────────────────────▶ HTML レスポンス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| snippets_controller.rb | `app/controllers/explore/snippets_controller.rb` | コントローラ | リクエストハンドリング |
| index.html.haml | `app/views/explore/snippets/index.html.haml` | テンプレート | メインビュー |
| _list.html.haml | `app/views/shared/snippets/_list.html.haml` | パーシャル | スニペット一覧表示 |
| _snippet.html.haml | `app/views/shared/snippets/_snippet.html.haml` | パーシャル | 個別スニペット表示 |
| snippets_finder.rb | `app/finders/snippets_finder.rb` | ファインダー | スニペット検索ロジック |
| snippet.rb | `app/models/snippet.rb` | モデル | Snippetモデル定義 |
| explore.rb | `config/routes/explore.rb` | ルーティング | URLルーティング定義 |
| noteable_metadata.rb | `lib/gitlab/noteable_metadata.rb` | ライブラリ | メタデータ取得ヘルパー |
