12
9

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 5 years have passed since last update.

Deviseのサインイン後のリダイレクト先は5パターン

Last updated at Posted at 2019-12-14

結論

以下、5パターン。上から順に優先度が高い。

usersというモデルにdeviseをマッピングさせた場合、

  • ログイン前にアクセスしようとしたページ
  • user_root_path(as: user_root_pathを指定したパターン)
  • user_root_path(名前空間 + rootで設定したパターン)
  • root_path(deviseマッピングとは関係ないroot_path)
  • "/"

詳細(サインインの観点から)

「サインイン後のリダイレクト先を設定したい!!」
となると、after_sign_in_path_forメソッドを使いますが、
きちんと理解しておかないと、「なんかうまくいかないな」という状態になりがちです。
しっかりやっていきましょう。

下記は、after_sign_in_path_forのソースです。
Git_Hub:after_sign_in_path_forメソッド

devise/lib/devise/controllers/helpers.rb
def after_sign_in_path_for(resource_or_scope)
  stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
end

さすが有名gemです。メソッド名でなんとなくわかりますね!!

  • stored_location_for(resource_or_scope)
     未ログイン時にアクセスしようとしたページがあった場合、サインインした後に飛ばす。

  • signed_in_root_path(resource_or_scope)
    いきなりログインページにアクセスした場合は、このメソッドの戻り値の場所に飛ばす。

ログイン後のリダイレクト先の理解には、
**signed_in_root_path(resource_or_scope)**メソッド
の理解がキーになりそうです。

早速見てみましょう。

devise/lib/devise/controllers/helpers.rb
def signed_in_root_path(resource_or_scope)
 # モデルオブジェクトが渡されると、deviseでマッピングされたスコープ(usersとか)を返す。
 # もしdeviseでマッピングしているモデルがadminという名前空間に属している場合、:admin_usersになる。
 scope = Devise::Mapping.find_scope!(resource_or_scope)

 # deviseを使うモデルが複数ある場合、mappings(ハッシュ)のうち[scope]を取得し、そのrouter_nameを代入する。
 # router_nameは、Devise::Mappingに対してoptionが渡されないとnilになるから基本nilっぽい。
 router_name = Devise.mappings[scope].router_name
 home_path = "#{scope}_root_path"

 # router_nameは基本nilっぽいので、実行されない。selfはobjectクラスのmain。
 context = router_name ? send(router_name) : self

 # contextに対してhome_pathを呼べるなら実行。trueはhome_pathがプライベートメソッドでも呼ぶよの意味。
 if context.respond_to?(home_path, true)
  context.send(home_path)
 # contextに対して、root_pathを呼べるなら実行。
 elsif context.respond_to?(:root_path)
  context.root_path
 # ただのroot_pathが呼べるなら実行。
 elsif respond_to?(:root_path)
  root_path
 # トップページにリダイレクト
 else
  "/"
 end
end

ふむふむ。

  • context.respond_to?(home_path, true)

  • context.respond_to?(:root_path)
    の違いだけちょっとあいまいだが、

  • admin/users#indexとかの名前空間(admin)があるパターンは、
    context.respond_to?(home_path, true)で実行される

  • 名前空間(admin)がないパターン(usersのみ)は
    context.respond_to?(:root_path)で実行される

と理解した。

home_path = "#{scope}_root_path"の#{scope}は、
adminとかの名前空間 + deviseでマッピングしているモデル名となる。

最終的にuser_root_pathとなるのは同じだが、内部的には意味が違うのではないだろうか。。。

下記は、user_root_pathで、home_pathと合致する。
devieでマッピングされたモデルに対して、home_pathはあるか?と聞いている。
context.respond_to?(home_path, true)

get to: "users#index", as: user_root_path

下記は、user_root_pathだが、home_pathとは合致しない。
deviseでマッピングされたモデルに対して、root_pathはあるか?と聞いている。
context.respond_to?(:root_path)

namespace users do
 root to: "users#index"
end 

認識違いあれば、ご指摘ください!!

参考URL

12
9
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
12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?