0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Devise 複数のモデルで同時にログイン出来ないようにする方法

Posted at

はじめに

例としてECサイトなどで、deviseをつかってUserモデルとStoreモデルを作成した場合、デフォルトではそれぞれのモデルで同時にログインや新規登録が可能です。今回はそれを修正したいと思います。

コントローラーを表示する

$
rails generate devise:controllers users
rails generate devise:controllers admins

ルーティング

config/routes.rb
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations'}
devise_for :stores, controllers: { sessions: 'stores/sessions', registrations: 'stores/registrations'}

これを忘れるとコントローラー内でオーバーライドした内容が反映されないので注意しましょう。

モジュールの作成

../controllers/concerns/accessible.rb
module Accessible
  extend ActiveSupport::Concern
  included do
    prepend_before_action :check_user
  end

  protected
  def check_user
    if current_store
      flash[:notice] = '店舗として既にログインしています。'
      redirect_to(current_store) and return
    elsif current_user
      flash[:notice] = 'ユーザーとして既にログインしています。'
      redirect_to(root_path) and return
    end
  end
end

check_userメソッドではそれぞれのモデルでログインしている場合はリダイレクトする処理を行っています。
これをコールバックに登録するのですが、理由は後述しますがbefore_actionではなくprepend_before_actionに登録しています。

モジュールの読み込み

../controllers/users/registration_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  include Accessible
  skip_before_action :check_user, except: [:new, :create]
  .
  .
  .
end

ここでは、自分のアカウント情報にアクセスして編集する目的と、edit,update,destroyアクションはdeviseのデフォルトの機能によりログインしているアカウントしかアクセス出来ないという理由でchek_userメソッドを呼び出していません。

../controllers/users/sessions_controller.rb
class Stores::SessionsController < Devise::SessionsController
  include Accessible
  skip_before_action :check_user, only: :destroy
  .
  .
  .
end

ログアウトする必要があるのでdestroyアクションには適用していません。
これで完成です。

before_actionではなくprepend_before_actionにコールバック関数を登録している理由

devise/app/controllers/devise/sessions_controller.rb
より、

.
.
prepend_before_action :require_no_authentication, only: [:new, :create]
prepend_before_action :allow_params_authentication!, only: :create
.
.
.
# POST /resource/sign_in
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message!(:notice, :signed_in)
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with resource, location: after_sign_in_path_for(resource)
  end

createアクションにはprepend_before_actionが登録されており、それらのメソッドが実行されると
current_userがtrueを返してしまいます。よってモジュール内で指定したcheck_userメソッドはprepend_before_actionに登録する必要があります。

参考

最後に

:require_no_authenticationメソッドや:allow_params_authentication!の中身をちゃんと理解していないので理解したいと思います。
何か間違った点や理解が怪しそうなところがあれば是非ご教授ください!

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?