# 画面設計書 41-グループ管理編集フォーム

## 概要

本ドキュメントは、Fat Free CRMの管理画面におけるグループ編集フォームの設計書です。管理者がユーザーグループの情報を編集するためのAjaxモーダルフォームを定義します。

### 本画面の処理概要

本画面は、管理者が既存のグループ情報を編集するための入力フォームです。グループはアクセス権限管理において重要な役割を果たし、ユーザーを論理的にグルーピングすることで、レコードの共有やアクセス制御を効率的に行うことができます。

**業務上の目的・背景**：組織内のユーザーを部門やプロジェクトなどの単位でグループ化し、CRMデータへのアクセス権限を一括管理するために必要です。グループを適切に設定することで、チーム単位でのデータ共有が可能となり、情報セキュリティと業務効率の両立を実現します。

**画面へのアクセス方法**：管理画面のグループ管理一覧画面から、編集したいグループの「Edit」リンクをクリックすることでAjaxモーダルとして表示されます。URL直接アクセスの場合は `/admin/groups/:id/edit` となります。

**主要な操作・処理内容**：
1. グループ名の編集
2. グループに所属するユーザーの選択・変更（複数選択可能）
3. 保存ボタンによるグループ情報の更新
4. キャンセルによる編集取り消し

**画面遷移**：グループ管理一覧画面（No.38）から遷移し、保存完了後は一覧画面に戻ります。キャンセル時も一覧画面に戻ります。

**権限による表示制御**：管理者（admin権限を持つユーザー）のみがアクセス可能です。一般ユーザーがアクセスしようとした場合は、管理画面トップへリダイレクトされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 67 | グループ編集 | 主機能 | グループ名の変更、所属ユーザーの追加・削除 |

## 画面種別

編集（モーダル/Ajax）

## URL/ルーティング

- **URL**: `/admin/groups/:id/edit`
- **HTTPメソッド**: GET（フォーム表示）、PUT/PATCH（更新実行）
- **ルーティング定義**: `config/routes.rb` 内の `namespace :admin do resources :groups end`
- **コントローラ**: `Admin::GroupsController#edit`, `Admin::GroupsController#update`

## 入出力項目

| 項目名 | 項目ID | データ型 | 必須 | 最大長 | 入力形式 | 備考 |
|--------|--------|----------|------|--------|----------|------|
| グループ名 | group[name] | string | Yes | 255 | テキスト | 一意性制約あり |
| 所属ユーザー | group[user_ids][] | integer配列 | No | - | 複数選択 | Select2による複数選択UI |

## 表示項目

| 項目名 | 表示形式 | データソース | 備考 |
|--------|----------|--------------|------|
| グループ名入力欄 | text_field | @group.name | 現在の名前を初期表示 |
| ユーザー選択リスト | select multiple | User.all | 全ユーザーを選択肢として表示、Select2適用 |
| 保存ボタン | submit | - | "Save Group" ラベル |
| キャンセルリンク | link | - | フォームを閉じる |

## イベント仕様

### 1-グループ名入力

フォームのテキストフィールドにグループ名を入力します。入力値は `group[name]` パラメータとしてサーバーに送信されます。

### 2-ユーザー選択

Select2コンポーネントを使用した複数選択UIで、グループに所属させるユーザーを選択します。選択されたユーザーIDは `group[user_ids][]` 配列としてサーバーに送信されます。

### 3-保存ボタン押下

- **処理フロー**:
  1. Ajaxリクエストで `PUT /admin/groups/:id` を呼び出し
  2. `Admin::GroupsController#update` が実行される
  3. `@group.update(group_params)` でグループ情報を更新
  4. `groups_users` 中間テーブルの関連レコードが更新される
  5. 成功時: フォームが閉じられ、一覧が更新される
  6. 失敗時: エラーメッセージがフォーム上に表示される

### 4-キャンセルリンク押下

- **処理フロー**:
  1. Ajaxリクエストで `GET /admin/groups/:id/edit` を呼び出し（同一URLのため、フォーム非表示処理）
  2. モーダルフォームが閉じられる
  3. 一覧画面の状態が維持される

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | groups | UPDATE | グループ名を更新 |
| 保存ボタン押下 | groups_users | DELETE/INSERT | ユーザー関連を再構築 |

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

#### groups

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | name | フォーム入力値 `group[name]` | 必須、一意性チェックあり |
| UPDATE | updated_at | 現在時刻 | ActiveRecordにより自動設定 |

#### groups_users（中間テーブル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | 既存の関連レコードを削除 | group_idに紐づく全レコード |
| INSERT | group_id | 対象グループのID | - |
| INSERT | user_id | 選択されたユーザーID | user_ids[]配列の各要素 |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 | 表示位置 |
|---------------|------|---------------|----------|
| エラー | グループ名が空 | "Name can't be blank" | フォーム上部 |
| エラー | グループ名が重複 | "Name has already been taken" | フォーム上部 |
| 成功 | 更新成功時 | （Ajax更新のため明示的メッセージなし） | - |

## 例外処理

| 例外条件 | 処理内容 | 表示・動作 |
|----------|----------|-----------|
| グループが見つからない | RecordNotFound例外 | 404エラーページを表示 |
| 権限不足（非管理者） | before_actionでリダイレクト | 管理画面トップへリダイレクト |
| バリデーションエラー | エラーメッセージ表示 | フォーム上部にエラー内容を表示、入力値は保持 |
| 通信エラー | Ajaxエラーハンドリング | クライアント側でエラー表示 |

## 備考

- 本フォームはAjaxモーダルとして実装されており、ページ全体のリロードなしに編集操作が完了します。
- Select2ライブラリを使用しているため、ユーザー選択UIは検索・フィルタリング機能を備えています。
- グループとユーザーの関連は `has_and_belongs_to_many` で実装されており、中間テーブル `groups_users` を使用します。
- `one_submit_only` ヘルパーにより、二重送信が防止されています。

---

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

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

### 推奨読解順序

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

まず、グループとユーザーの関連を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | group.rb | `app/models/users/group.rb` | Groupモデルの定義、バリデーション、ユーザーとの関連 |
| 1-2 | schema.rb | `db/schema.rb` | groupsテーブル（273-277行目）、groups_usersテーブル（279-285行目）の構造 |

**読解のコツ**: `has_and_belongs_to_many :users` の記述に注目し、中間テーブル `groups_users` を介した多対多関連を理解してください。

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

処理の起点となるコントローラアクションを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | groups_controller.rb | `app/controllers/admin/groups_controller.rb` | edit/updateアクションの実装 |

**主要処理フロー**:
1. **32-35行目**: `edit` アクション - `load_resource` により `@group` が自動ロードされる
2. **48-52行目**: `update` アクション - `group_params` を使用してグループを更新
3. **64-66行目**: `group_params` メソッド - Strong Parametersによるパラメータ許可

#### Step 3: ビューテンプレートを理解する

フォームの構造とレンダリングを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _edit.html.haml | `app/views/admin/groups/_edit.html.haml` | 編集フォームのメインテンプレート |
| 3-2 | _form.html.haml | `app/views/admin/groups/_form.html.haml` | フォーム入力項目の定義 |

**主要処理フロー**:
- **2行目（_edit.html.haml）**: `form_for([:admin, @group], ...)` でリソースフルなフォームを生成
- **7行目（_edit.html.haml）**: `render "admin/groups/form"` でフォーム本体をレンダリング
- **6行目（_form.html.haml）**: グループ名入力フィールド
- **11行目（_form.html.haml）**: ユーザー複数選択（Select2）

#### Step 4: ルーティングを理解する

URLとコントローラの対応を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | routes.rb | `config/routes.rb` | admin名前空間内のgroupsリソース定義（166行目） |

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

```
ブラウザ（Edit リンク クリック）
    │
    ├─ GET /admin/groups/:id/edit (Ajax)
    │      │
    │      └─ Admin::GroupsController#edit
    │             │
    │             ├─ load_resource (CanCanCan)
    │             │      └─ Group.find(params[:id])
    │             │
    │             └─ respond_with(@group)
    │                    └─ _edit.html.haml レンダリング
    │                           └─ _form.html.haml レンダリング
    │
    └─ PUT /admin/groups/:id (Ajax)
           │
           └─ Admin::GroupsController#update
                  │
                  ├─ @group.update(group_params)
                  │      │
                  │      ├─ Group バリデーション
                  │      │      └─ validates :name, presence: true, uniqueness: true
                  │      │
                  │      └─ groups_users 関連更新
                  │             └─ DELETE/INSERT
                  │
                  └─ respond_with(@group)
                         └─ update.js.erb レンダリング
```

### データフロー図

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

ユーザー操作
(Edit クリック) ───▶ GroupsController#edit ───▶ 編集フォーム表示
                            │
                            └─ Group.find(:id)

フォーム入力
 ├─ group[name]
 └─ group[user_ids][] ───▶ GroupsController#update
                                  │
                                  ├─ group_params
                                  │      └─ Strong Parameters
                                  │
                                  └─ @group.update
                                         │
                                         ├─▶ groups テーブル (UPDATE)
                                         │
                                         └─▶ groups_users テーブル
                                                (DELETE/INSERT)
                                                      │
                                                      └─▶ 一覧画面更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| group.rb | `app/models/users/group.rb` | モデル | グループエンティティ、バリデーション、関連定義 |
| groups_controller.rb | `app/controllers/admin/groups_controller.rb` | コントローラ | edit/updateアクション処理 |
| _edit.html.haml | `app/views/admin/groups/_edit.html.haml` | ビュー | 編集フォームのラッパー |
| _form.html.haml | `app/views/admin/groups/_form.html.haml` | ビュー | フォーム入力項目定義 |
| routes.rb | `config/routes.rb` | 設定 | URLルーティング定義 |
| schema.rb | `db/schema.rb` | 設定 | データベーススキーマ |
| application_controller.rb | `app/controllers/admin/application_controller.rb` | コントローラ | 管理画面基底コントローラ、認証・認可 |
