【Rails・devise】複数モデルを管理する際の<<before_action>>


はじめに

deviseを用いて一般の方とグループ(企業や団体等)で分けてログインを実装する上で、
ログインした人のみが閲覧できるbefore_actionの実装に手間取ってしまったので記録します!

結果から

applicationコントローラーで
・グループの方がログインした場合 → authenticate_any!が有効
・それ以外の人がログインした場合 → authenticate_user!が有効

application_controller.rb
class ApplicationController < ActionController::Base
  def authenticate_any!
    if group_signed_in?
        true
    else
        authenticate_user!
    end
  end
end

各コントローラーで必要なところでbefore_action :authenticate_any!を記載する
application_controller.rbに記載して全て制限したいのであれば
before_action :authenticate_any!の下でauthenticate_any!を定義する

posts_controller.rb
before_action :authenticate_any!

無事、ログインについてのRspecも通りました!

ハマったこと

userまたはgroupがログインしている場合のみページにアクセスができるように実装したかったので、
左から順に評価し、最初に真になったものを返してくれる||を使用してみました。

posts_controller.rb
before_action :authenticate_user! || :authenticate_group!

こうするとauthenticate_user!は反応するもののgroupが反応せず、
groupを作成できるもののroot_pathでCompleted 401 Unauthorizedとエラーが発生して、
弾き出されてuserのsign_inページにリダイレクトされてしまっていました。

Completed 401 UnauthorizedでググるとCSRF トークンの不整合がでてくることが多かったので、
application_controller.rbにprotect_from_forgery with: :null_session記載をして
対応したりもしましたが、ダメでした。。。
(これはCSDF 対策として弱くなるという意見もあるみたいなので、そもそも使わないほうがいいのかも・・・)

学んだこと

before_actionで場合分けしたい場合は、メソッドを作成してその中で条件分けをする!

今までなんとなくbefore_actionを使用していましたが、勉強になりました!(かなり初歩的なのかとは思いますが笑)

同じようなことに困っている方のお役に立てたら嬉しいです。