はじめに
DeviseをしようしているRailsのアプリケーションで、データベースにユーザーのレコードはあるがそのユーザーにはログインさせたくない時にする実装をする機会があった。はじめは authenticate_user! メソッドを上書きしようとしたが、少し調べた結果 active_for_authenticatation? というユーザーモデルのインスタンスメソッドを上書きするのが良いことに気づいた。以下に実際に特定の条件のユーザーのログインを不可にする実装とその際のエラーメッセージの設定の仕方を書いた。
参照:
How To: Customize user account status validation when logging in
Module: Devise::Models::Authenticatable
実装
例:
- Userモデルにデバイスをインストールしている
- 運営のメールに返信していないアカウントのログインを不可にしたい
- 運営のメールに返信したかどうかは
usersテーブルのmail_replyカラムが0か1で表されている
特定の条件のユーザーのログインを不可にする実装
DeviseのGithub Wikiページに に書いてあるとおりログイン時にバリデーションを足したい場合はUserモデルの active_for_authentication?を上書きします。このメソッドはログイン時にDeviseが呼び出しています。今回の例ではコードは以下のとおりになります。
class User < ApplicationRecord
def active_for_authentication?
super && mail_reply?
end
end
エラーメッセージの変更
active_for_authentication? メソッドが false を返すと、Deviseは Account Not Active Error のメッセージを表示します。ですが、今回は「運営のメールに返信していないこと」を伝えたいので、独自のメッセージを表示したいです。
こちらにあるように、 active_for_authentication? が false を返すと Userモデルのインスタンスメソッドの inactive_message を呼び出し、デフォルトでは Account Not Active のエラーメッセージを表示します。なので、inactive_message を上書きましよう。
class User < ApplicationRecord
def active_for_authentication?
super && mail_reply?
end
def inactive_message
mail_reply? super : :mail_not_replied
end
end
デフォルトでは locales/device.en.yml の en.devise.failure.inactive のメッセージを表示するところを、運営のメールを返していない場合は en.devise.failure.mail_not_replied のメッセージを表示するようになります。日本語化をされている場合は locales/device.ja.ymlの ja.devise.failure.inactive と ja.devise.failure.mail_not_replied になります。
ですが、現在は mail_not_replied のメッセージがないので追加してあげる必要があります。
英語の場合
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
# 略
failure:
# 略
# ここに追加
mail_not_replied: "Please reply mail from our company."
mailer:
# 略
日本語の場合
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
# 略
failure:
# 略
# ここに追加
mail_not_replied: "運営からのメールを返信していません"
mailer:
# 略
上記のようにすると運営からのメールを返していないアカウントのログインを不可にできると思います。質問、コメント、指摘などあればコメントしていただけると幸いです。