email以外のキーを使った認証方法について、devise単体では同じような記事がいくつもありましたが、devise-token-authを交えた記事があまりなかったので作成しました。
上記の記事等を参考にしましたが、devise-token-auth側でdevise本体の挙動が色々とオーバーライドされており、そのままの設定では動作しない部分がありました。
右往左往しましたが、結果的には思っていたよりも少ない修正で実現できましたので、同様のことでお悩みの方の参考になれば幸いです。
usersテーブルにusernameを追加する
以下のようにユニーク制約を付与してstring型のusernameをusersテーブルに追加します。
class AddUsernameToUsers < ActiveRecord::Migration[7.0] def change add_column :users, :username, :string add_index :users, :username, unique: true end end
Userモデルへの設定
authentication_keysの設定
deviseメソッドのauthentication_keysにemailとusernameを設定します。
devise :database_authenticatable, :registerable, :rememberable, :trackable, :validatable, authentication_keys: %i[email username] # ←この部分を設定します
こうすることで、emailまたはusernameが認証キーとして設定されるようになります ログイン時はどちらか一方のキーで認証することが可能となります。
バリデーションの設定
このままでは、usernameに対してバリデーションが全く効いていない状態なので、以下のようにバリデーションを設定します。
validates :username, presence: true, uniqueness: true
emailに対しては:validatableが有効であれば自動でバリデーションチェックが走ります。
任意で細かなチューニング
基本的には上記の設定変更のみでemailまたはusernameでログインすることが可能となります。
ただし現状のままでは不完全な部分があります。
例えばemailとusernameに同じ値が設定できてしまうので考慮が必要です。 また、ユーザー情報変更(account_update)時にusernameが変更できませんので、そこの考慮もする必要があるかと思います。
必要に応じて以下の記事を参考にチューニングを行ってください。