🍣

チームメンバーのエラー解消/deviseログイン条件について

2023/08/28に公開

はじめに

毎日チームメンバーと進捗報告会をやっていて、その時にメンバーのエラー解消を一緒に考えることがあります。
今日はdeviseのadmin側はemail/password、public側はname/passwordでログインしたいがpublic側のログインをするときにemailを求められてしまう状況を解消しました。
ついでにdeviseの導入もまとめました。

Devise の導入

まずdeviseでGem をインストールした後に、改めてインストールをします。

ターミナル
$ rails g devise:install
ターミナル
【顧客用】
$ rails g devise Customer

【管理者用】
$ rails g devise Admin

コントローラー作成

以下の記述でadmin側とpublic側のcontrollerを作成します。

【顧客用】
$ rails g devise:controllers public

【管理者用】
$ rails g devise:controllers admin

管理者側の View の編集をします。

View 作成の際に admins から admin にフォルダ名を変更したことにより
下記のように記述されているのが原因で、ファイルが存在しないというエラーが発生するため修正を行いましょう。
今回管理者側は、ログイン機能のみを使用するためapp/views/admin/sessions/new.html.erbのみ修正を行います。

app/views/admin/sessions/new.html.erb
【変更前】
<%= render "admins/shared/links" %>
【変更後】
<%= render "admin/shared/links" %>

顧客側のViewの編集

管理者側と同様、publicフォルダにフォルダ名を変更したことにより、エラーが発生するため修正を行いましょう。
顧客側は、登録機能とログイン機能を使用するためapp/views/public/registrations/new.html.erbと
app/views/public/sessions/new.html.erbの修正を行います。

app/views/public/registrations/new.html.erb,app/views/public/sessions/new.html.erb
【変更前】
<%= render "publics/shared/links" %>
【変更後】
<%= render "public/shared/links" %>

また、新規登録画面でのエラーメッセージを呼び出している部分でもエラーが発生するため、同様に修正します。

app/views/public/registrations/new.html.erb
【修正前】
<%= render "publics/shared/error_messages", resource: resource %>
【修正後】
<%= render "public/shared/error_messages", resource: resource %>

ルーティングの編集

デフォルトでいかのような記述になっていると思います。

config/routes.rb
devise_for :customers
devise_for :admins

この記述だと、先程作成したコントローラーの記述を変更してもその処理を行うことができないので編集します。

config/routes.rb
# 顧客用
# URL /customers/sign_in ...
devise_for :customers, controllers: {
  registrations: "public/registrations",
  sessions: 'public/sessions'
}

# 管理者用
# URL /admin/sign_in ...
devise_for :admin, controllers: {
  sessions: "admin/sessions"
}

これで基本的な実装はできていると思います。

機能の追加や削除を行う場合には以下のファイルを編集します。app/views/public/shared/_links.html.erb
app/views/admin/shared/_links.html.erb

複数モデルでdeviseを利用するときに特定のモデルだけauthentication_keysを変更したい

ログインに利用するキーを変更するには通常 config/initializers/devise.rbの中のconfig.authentication_keys = [:email]を変更すればよいが、ここを変更すると全てのモデルに反映されてしまいます。
その為特定のモデルだけの場合は以下のようにdeviseのoptionとして指定すればできるようになります。
user側のログイン条件をnameとpasswordにする場合には以下のようになります。

model
class Customer < ApplicationRecord
  devise :database_authenticatable, authentication_keys: [:name, :enqupy_password]

  # 企業IDとメールアドレスでログインをする
  def self.find_for_database_authentication(warden_conditions)
    email = warden_conditions[:name].to_s.downcase.strip
    find_by(name: name, enqupy_password: warden_conditions[:enqupy_password])
  end
end

参考にさせていただいた記事

https://remoter.hatenablog.com/entry/2020/07/07/複数モデルでdeviseを利用するときに特定のモデルだ

まとめ

他人のエラーを解消するときは自分の書いたコードではないので、読みやすい読みやすくないの違いがなんとなく感覚で分かった気がします。これを言語化できるようにどんどん相談にのって違いを知るのが大事だと実感しました!

Discussion