# 機能設計書 69-アバター削除

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるプロフィール画像（アバター）を削除する機能の設計を詳述する。

### 本機能の処理概要

**業務上の目的・背景**：ユーザーがアップロードしたアバター画像を削除し、デフォルトのイニシャル表示に戻す機能が必要である。不適切な画像をアップロードした場合や、画像を使用したくなくなった場合に利用される。

**機能の利用シーン**：プロフィール編集画面でアバター削除ボタンをクリックする場面で利用される。削除確認ダイアログで承認後に実行される。

**主要な処理内容**：
1. ユーザーの特定
2. 権限チェック（can_change?）
3. Active Storageのアバター添付を削除
4. プロフィール画面にリダイレクト

**関連システム・外部連携**：Active Storageによるファイル削除。

**権限による制御**：can_change?メソッドで権限を判定。自分自身または管理者（admin）のみが削除可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 39 | プロフィール編集画面 | 主画面 | アバターを削除 |

## 機能種別

データ削除処理（DELETE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| user_id | UUID | Yes | ユーザーID（URLパラメータ） | Current.account.users内に存在 |

### 入力データソース

- URLパラメータ（user_id）
- 確認ダイアログからの承認（turbo_confirm）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| リダイレクト先 | URL | /users/:id（プロフィール画面） |

### 出力先

- プロフィール画面へリダイレクト

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信（DELETE /users/:user_id/avatar）
   └─ Users::AvatarsController#destroy
2. ユーザー取得
   └─ set_user (before_action)
3. 権限チェック
   └─ ensure_permission_to_administer_user (before_action)
   └─ Current.user.can_change?(@user)
4. アバター削除
   └─ @user.avatar.destroy
5. リダイレクト
   └─ redirect_to @user
```

### フローチャート

```mermaid
flowchart TD
    A[DELETE /users/:user_id/avatar] --> B[set_user でユーザー取得]
    B --> C{ユーザーが存在?}
    C -->|No| D[404 Not Found]
    C -->|Yes| E[ensure_permission_to_administer_user]
    E --> F{can_change?}
    F -->|No| G[403 Forbidden]
    F -->|Yes| H[@user.avatar.destroy]
    H --> I[Active Storage添付を削除]
    I --> J[redirect_to @user]
    J --> K[プロフィール画面表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-69-01 | 自己削除可能 | 自分自身のアバターは常に削除可能 | other == self |
| BR-69-02 | 管理者削除可能 | 管理者は非オーナーユーザーのアバターを削除可能 | admin? && !other.owner? |
| BR-69-03 | オーナー保護 | オーナーのアバターは他者から削除されない | other.owner? |
| BR-69-04 | 確認必須 | 削除前に確認ダイアログを表示 | 常に |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 添付削除 | active_storage_attachments | DELETE | アバター添付レコードを削除 |
| Blob削除 | active_storage_blobs | DELETE | 画像Blobを削除（参照がなくなった場合） |
| Variant削除 | active_storage_variant_records | DELETE | サムネイルバリアントを削除 |

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

#### active_storage_attachments

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | record_type = 'User', record_id = @user.id, name = 'avatar' | 添付レコード削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | ActiveRecord::RecordNotFound | ユーザーが存在しない | Rails標準の404ページ |
| 403 | Forbidden | can_change?がfalse | head :forbidden |

### リトライ仕様

リトライ不要。

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

- @user.avatar.destroyは暗黙のトランザクションで実行
- Blobの物理削除は非同期で実行される可能性あり

## パフォーマンス要件

- レスポンス時間：500ms以内

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

- 認証必須
- can_change?による権限チェック
- 削除確認ダイアログ（turbo_confirm）による誤操作防止

## 備考

- 削除後はイニシャルSVGが表示される
- Blobの物理削除はActive Storageの設定に依存

---

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

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

### 推奨読解順序

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

Active Storageの添付構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | avatar.rb | `app/models/user/avatar.rb` | has_one_attached :avatarの定義 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | avatars_controller.rb | `app/controllers/users/avatars_controller.rb` | destroyアクション |

**主要処理フロー**:
1. **4行目**: before_action :set_user
2. **5行目**: before_action :ensure_permission_to_administer_user only: :destroy
3. **17-19行目**: destroyアクションで@user.avatar.destroyを実行
4. **27-29行目**: ensure_permission_to_administer_userでcan_change?チェック

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit.html.erb | `app/views/users/edit.html.erb` | 削除ボタンの実装 |

**読解のコツ**: edit.html.erbの22-27行目でアバターが添付されている場合に削除ボタンが表示される。turbo_confirmで確認ダイアログを表示。

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

```
Users::AvatarsController#destroy
    │
    ├─ before_action :set_user
    │      └─ Current.account.users.find(params[:user_id])
    │
    ├─ before_action :ensure_permission_to_administer_user
    │      └─ Current.user.can_change?(@user)
    │
    └─ @user.avatar.destroy
           │
           └─ ActiveStorage::Attached::One#destroy
                  │
                  ├─ DELETE active_storage_attachments
                  │
                  └─ (非同期) DELETE active_storage_blobs
                  │
                  └─ (非同期) DELETE active_storage_variant_records
```

### データフロー図

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

params[:user_id] ───▶ Current.account.users.find ───▶ @user
                              │
                              ▼
                    @user.avatar.destroy
                              │
                              ▼
                    active_storage_attachments DELETE
                              │
                              ▼
                    redirect_to @user
                              │
                              ▼
                    プロフィール画面（イニシャルSVG表示）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| avatars_controller.rb | `app/controllers/users/avatars_controller.rb` | コントローラー | アバター削除のエントリーポイント |
| avatar.rb | `app/models/user/avatar.rb` | モデルconcern | アバター添付の定義 |
| edit.html.erb | `app/views/users/edit.html.erb` | ビュー | 削除ボタンの表示 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（15行目） |
