Deviseでresource毎にログイン後のリダイレクト先を変えたい場合の自分なりの対応

皆さんdevise使っていますか?
Railsの認証にはdeviseがデファクトスタンダードになっていますよね。
今回は、deviseの認証で「user」と「admin」などのように違うresourceでログインしたあとのリダイレクト先の設定方法について自分なりの考えを記載しようと思います。
目次
- 環境
- リダイレクト先の設定方法
- resource毎の
root_path
を適切に定義する - なぜこれでresource毎にリダイレクトされるのか?
- 参考: devise-4.7.3/lib/devise/controllers/helpers.rb
- 参考: 調べるとよく出てくるパターン
- resource毎の
- なぜそう考えるのか?
- ログインやサインアップ、パスワード更新、などの度に設定する必要がでてくる
- 余計なコードは少ないほうが良い
- では調べるとよく出てくるパターンはいつ使うべきなのか?
- まとめ
1. 環境
- rails: 6.1
- devise: 4.7.3
2. リダイレクト先の設定方法
調べるとよく出てくるapplication_controller.rbでafter_xxx_path_forを上書きするのではなく、「resource毎のroot_path
を適切に定義する」という対応方法が良いのではないか?と思っています。
resource毎のroot_path
を適切に定義する
config/routes.rb
namespace :admin do
resource :dashboard, only: :show, as: :root
end
bin/rails routes | grep admin
admin_root GET /admin/dashboard(.:format) admin/dashboards#show
このように、config/routes.rb
で適切にnamespace, scope, moduleなどを切ってas: :root
を定義するとadmin_root_path
が定義され、ログイン後にそれぞれのresource毎に好きな画面に遷移させることができます。
なぜこれでresource毎にリダイレクトされるのか?
deviseでは以下のsigned_in_root_path
の通り、user_root_path
やadmin_root_path
などのresource毎のroot_pathが定義されていると、それを最優先して実行するためです。
参考: signed_in_root_path
devise-4.7.3/lib/devise/controllers/helpers.rb
# The scope root url to be used when they're signed in. By default, it first
# tries to find a resource_root_path, otherwise it uses the root_path.
def signed_in_root_path(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
router_name = Devise.mappings[scope].router_name
home_path = "#{scope}_root_path"
context = router_name ? send(router_name) : self
if context.respond_to?(home_path, true)
context.send(home_path)
elsif context.respond_to?(:root_path)
context.root_path
elsif respond_to?(:root_path)
root_path
else
"/"
end
end
参考: 調べるとよく出てくるパターン
app/controllers/application_controller.rb
def after_xxx_path_for
#{リダイレクト先}
end
3. なぜそう考えるのか?
- ログインやサインアップ、パスワード更新、などの度に設定する必要がでてくる
- 余計なコードは少ないほうが良い
1. ログインやサインアップ、パスワード更新、などの度に設定する必要がでてくる
deviseでの登録、更新、削除後のリダイレクト先のメソッドはafter_resetting_password_path_for
、after_update_path_for
、after_sign_in_path_for
、after_confirmation_path_for
のように複数あります。
それらを全部上書きするのはやっかいでバグの温床になる可能性が高いです。
上記の各メソッドの中では適切にsigned_in_root_path
が使われるため、resource毎のroot_path
を適切に定義すると全ての状況に対応できることになります。
2. 余計なコードは少ないほうが良い
application_controllerで上書きするパターンでも漏れなく上書きすれば期待通りのアプリケーションを得ることができますが、不必要なコードは少ないほうが読むのが楽という面もあります。
config/routes.rb
の設定は本来あるべき設定だと考えられるので、config/routes.rb
の設定だけで済むのであればこれに越したことがないと思います。
4. では調べるとよく出てくるパターンはいつ使うべきなのか?
同じresourceの中で、なにかしらの条件によってリダイレクト先を分ける場合には、after_xxx_path_forが便利だと思います。
例えば、権限、ステータスなどによって、遷移先が違う場合などです。
5. まとめ
deviseのリダイレクト先の設定方法について自分なりの考えを記載してみましたがいかがでしょうか?
適切にroot_pathを定義するとシンプルで少ないコードで意図した機能を実現できると思います。
改めてdeviseはよくできているなと思いました。
では良いdeviseライフを!!