deviseで作成したUserモデルに自分で設定したいフィールドを追加する方法

## やりたいこと
こんな感じでdeviseで作成したサインアップ機能にaccount名を入れられるようにしたい
![スクリーンショット 2024-09-13 180650.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875060/9f29c254-45bb-1447-3fd3-af34f9937671.png)

## 課題
- マイグレーション時にaccount用のカラムを作成する必要がある
- deviseが標準で設定しているストロングパラメーターをいじる必要がある

## マイグレーション時の対応
マイグレーションファイルに以下のように追記する
※今回はUniqueにしたかったので、その設定もしています
```
class DeviseCreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :username,           null: false #ここが追記
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      t.timestamps null: false
    end

    add_index :users, :username,             unique: true　　#ここが追記
    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
  end
end
```
### 地味なポイント
**unipueの設定はカラムの作成後、add_indexをする必要がある**
`t.string :username, null: false`　という設定に属性を追記する感じで、
`t.string :username, null: false, unipue: true`としたら行けるんじゃない？
と思ったのですが、仕様上できないようです。

## ストロングパラメーターをいじる
これでカラムあるし、フォームに:username追加したら完了！
と思っていたのですが、バリデーションエラーが発生します。

普通であれば、自分で作成したコントローラーに自分で記述したストロングパラメーターを変更するだけで済むのですが、deviseで作成した場合`users_controller`がないのでどうしよう…？となりました。

### 方法１:appllication_controllerをいじる
下記を記述すると解決しました。

```
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  # Deviseのストロングパラメーターをカスタマイズ
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
    devise_parameter_sanitizer.permit(:account_update, keys: [:username])
  end
```
`before_action :configure_permitted_parameters`はアクションの前に`configure_permitted_parameters`を実行する、という記述

`if: :devise_controller?`は微妙にわからなかったのですが、`devise_controller?`はdeviseが定義しているメソッドでリクエストがDeviseに関連するコントローラアクションから来ているかどうかを確認するためのもの。

`devise_parameter_sanitizer.permit(:sign_up, keys: [:username])`が今回のメイン。

`devise_parameter_sanitizer`もdeviseが定義しているメソッドで、そのまんまストロングパラメーターの許可を追加するのに使うメソッドらしい。
さすがdevise…

ついでにsign_upだけでなく、update時にもバリデーションエラーが起きないように記述をすれば完了！

### 方法2：Deviseコントローラをカスタマイズ
方法１で完了したのですが、ちょっと悩んだのが、application_controllerに記載するという点。
特に気になったのは以下の2点
- application_controllerはすべてのcontrollerに継承されるからScope的にどうなんだろう…
- if文で条件分岐するくらいなら最初からdeviseコントローラーをいじればいいんじゃない？

ということで調べてみたのですが、まずdeviseコントローラーをいじるのは非推奨らしいです。
理由は、deviseのアップデートなどがあった際に上書きされてしまう可能性があるためとのこと。

回避する方法として、deviseコントローラーを継承したコントローラー作ること。
以下のような感じ。
```
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_permitted_parameters

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
    devise_parameter_sanitizer.permit(:account_update, keys: [:username])
  end
end
```

ただ上記の場合、自分で作成したコントローラーにリクエストを飛ばせるようにroutesもいじる必要がある。
```
devise_for :users, controllers: {
  registrations: 'users/registrations'
}
```

どちらでも実現できそうですが、application_controllerのほうが一元管理という意味合いで良いみたい。
deviseのコントローラーから継承する形だとresistration,sessionなどそれぞれの機能毎にコントローラーを作成する形になるので、変更や修正があった場合に手間が増えるため。
メンテナンスまで考えて、今回はapplication_controllerの方にします。