行動すれば次の現実

テック中心の個人ブログ

devise-token-authでemailではなくusernameでもログインさせる方法

email以外のキーを使った認証方法について、devise単体では同じような記事がいくつもありましたが、devise-token-authを交えた記事があまりなかったので作成しました。

How To: Allow users to sign in using their username or email address · heartcombo/devise Wiki · GitHub

上記の記事等を参考にしましたが、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が変更できませんので、そこの考慮もする必要があるかと思います。

必要に応じて以下の記事を参考にチューニングを行ってください。

github.com