0
1

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

Posted at

やりたいこと

こんな感じでdeviseで作成したサインアップ機能にaccount名を入れられるようにしたい
スクリーンショット 2024-09-13 180650.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がないのでどうしよう…?となりました。

方法1: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コントローラをカスタマイズ

方法1で完了したのですが、ちょっと悩んだのが、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の方にします。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1