# 画面設計書 36-通知解除画面

## 概要

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

### 本画面の処理概要

通知解除画面は、メール通知の配信を停止するための画面です。メール内の解除リンクからアクセスでき、ワンクリックで通知を停止できます。

**業務上の目的・背景**：ユーザーがメール通知を受け取りたくない場合、簡単に解除できる手段を提供する必要があります。特に、ログインせずにメールから直接解除できることは、ユーザー体験とスパム対策の観点から重要です。本画面は、トークンベースの認証によりログイン不要で通知解除を可能にします。

**画面へのアクセス方法**：通知メール内の「Unsubscribe」リンクからアクセスします。リンクにはアクセストークンが含まれています。

**主要な操作・処理内容**：
1. 解除対象ユーザーの確認
2. 「Unsubscribe now」ボタンをクリックして解除実行
3. 自動送信フォームによる即時解除

**画面遷移**：
- 遷移元：通知メール内のリンク
- 遷移先：通知解除完了画面

**権限による表示制御**：トークンにより認証されるため、ログイン不要です。無効なトークンの場合はホーム画面にリダイレクトされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 61 | 通知配信停止 | 主機能 | メール通知の配信を停止 |

## 画面種別

確認/実行

## URL/ルーティング

- **パス**: `/notifications/unsubscribe/new`
- **HTTPメソッド**: GET（表示）
- **コントローラ**: `Notifications::UnsubscribesController#new`

## 入出力項目

| 項目名 | 項目ID | 入出力 | データ型 | 必須 | 最大長 | 説明 |
|--------|--------|--------|----------|------|--------|------|
| アクセストークン | access_token | 入力 | String | 必須 | - | メール解除用トークン |

## 表示項目

| 項目名 | 説明 | データ取得元 |
|--------|------|-------------|
| 解除メッセージ | 「Unsubscribing from all email notifications as {name}...」 | @user.name |
| Unsubscribe nowボタン | 解除実行ボタン | - |

## イベント仕様

### 1-通知解除実行

メール通知を解除します。

- **トリガー**: フォームの自動送信、または「Unsubscribe now」ボタンクリック
- **処理フロー**:
  1. POST `/notifications/unsubscribe` を送信（access_tokenパラメータ付き）
  2. `@user.settings.bundle_email_never!` でメール頻度をneverに設定
  3. 通知解除完了画面へリダイレクト
- **データ更新**: user_settings.bundle_email_frequency = 0 (never)

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | users | SELECT | トークンからユーザーを取得 |
| 解除実行 | user_settings | UPDATE | メール頻度をneverに更新 |

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

#### user_settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | bundle_email_frequency | 0 (never) | bundle_email_never!メソッド |
| UPDATE | updated_at | 現在時刻 | 自動更新 |

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|------------|---------------|---------|
| 情報 | unsubscribing | Unsubscribing from all email notifications as {name}... | 画面表示時 |
| エラー | invalid_link | Invalid unsubscribe link | 無効なトークン |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|-----|---------|---------|
| 無効なトークン | トークンが存在しないまたは期限切れ | ホーム画面にリダイレクト（アラート付き） |

## 備考

- ログイン不要でアクセス可能（allow_unauthenticated_access）
- CSRF保護は無効化（skip_forgery_protection）
- トークンは`User.find_by_token_for(:unsubscribe, token)`で検証
- 自動送信フォーム（auto_submit_form_with）により、ページロード後に自動的にフォームが送信される
- delayed-fade-inクラスで遅延表示

---

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

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

### 推奨読解順序

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

トークンベースの認証とユーザー設定を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | Userモデル、generates_token_forの定義 |
| 1-2 | settings.rb | `app/models/user/settings.rb` | bundle_email_never!メソッド |

**読解のコツ**: Railsの`generates_token_for`を使用してunsubscribe用のトークンを生成。enumのbang!メソッドで直接値を設定。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | unsubscribes_controller.rb | `app/controllers/notifications/unsubscribes_controller.rb` | 認証スキップ、トークン検証 |

**主要処理フロー**:
1. **2行目**: `allow_unauthenticated_access` でログイン不要
2. **3行目**: `skip_forgery_protection` でCSRF保護を無効化
3. **5行目**: `before_action :set_user` でトークンからユーザーを取得
4. **10-12行目**: createアクションでbundle_email_never!を実行

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

通知解除画面のテンプレート構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.erb | `app/views/notifications/unsubscribes/new.html.erb` | 自動送信フォーム |

**主要処理フロー**:
- **1行目**: 解除対象ユーザー名を表示
- **4行目**: `auto_submit_form_with` で自動送信フォームを生成

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

```
Notifications::UnsubscribesController#new
    │
    ├─ allow_unauthenticated_access (認証スキップ)
    │
    ├─ skip_forgery_protection (CSRFスキップ)
    │
    ├─ set_user
    │      │
    │      ├─ User.find_by_token_for(:unsubscribe, params[:access_token])
    │      │
    │      └─ トークン無効 → redirect_to root_path, alert: "Invalid unsubscribe link"
    │
    └─ render new.html.erb
           │
           └─ auto_submit_form_with → POST /notifications/unsubscribe

Notifications::UnsubscribesController#create
    │
    ├─ set_user (トークン検証)
    │
    ├─ @user.settings.bundle_email_never!
    │      │
    │      └─ User::Settings#bundle_email_frequency = "never"
    │
    └─ redirect_to notifications_unsubscribe_path(access_token: params[:access_token])
```

### データフロー図

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

メールリンク             UnsubscribesController#new
  access_token ─────────▶ トークン検証
                              │
                        ┌─────┴─────┐
                       有効        無効
                        │           │
                        ▼           ▼
                   @user取得    redirect root_path
                        │          (alert)
                        ▼
                   new.html.erb
                        │
                   auto_submit_form
                        │
                        ▼
                   POST /unsubscribe
                        │
                        ▼
                   bundle_email_never!
                        │
                        ▼
                   完了画面へリダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| unsubscribes_controller.rb | `app/controllers/notifications/unsubscribes_controller.rb` | コントローラ | 通知解除処理 |
| new.html.erb | `app/views/notifications/unsubscribes/new.html.erb` | テンプレート | 解除確認画面 |
| settings.rb | `app/models/user/settings.rb` | モデル | ユーザー設定 |
| user.rb | `app/models/user.rb` | モデル | ユーザーモデル |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（109行目） |
