解決したいこと
Railsのgemであるdeviseでユーザー管理を実装する際、
ログイン後に遷移するページを指定する方法。
結論
after_sign_in_path_forというヘルパーを利用する。
ヘルパー内で、ログイン後に遷移させたいパスを指定する。
実装したコード
- deviseは導入済みで、サインアップ・サインイン・ログアウト機能は実装済
- rails g controller usersを実行して、usersコントローラーを作成済み
config/routes.rb
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:show] #追加したルーティング
end
app/controllers/application_controller.rb
private
def after_sign_in_path_for(resource)
user_path(resource)
end
usersコントローラーのshowアクションを呼び出すパスを設定。
privateメソッドでも問題なく動作したため、こちらに定義した。
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
def show
@user = User.find(params[:id])
end
end
マイページ(app/views/users/show.html.erb)で、ユーザー情報を使用するため、
usersテーブルから、該当idのユーザーレコードをとってくる様に設定。
また、ログインしていないユーザーを強制的にログインページへ飛ばすため、
usersコントローラー側でauthenticate_user!を設定した。
ヘルパーの引数resourceは何か
結論:「ログインユーザーのレコード(インスタンス)」
実装コードで動作確認はできた。
しかし、「resourceには何が渡されているのか?」と気になった。
binding.pryで調べてみると
resourceには、ログインユーザーのレコードが入っていた。
paramsには、ログイン時に入力した情報が乗っていた。
16: def after_sign_in_path_for(resource)
17: user_path(resource.id)
=> 18: binding.pry
19: end
[1] pry(#<Devise::SessionsController>)> resource
=> #<User id: 2, email: "test@test", nickname: "テスト", created_at: "~(省略)", updated_at: "~(省略)">
[2] pry(#<Devise::SessionsController>)> params
=> <ActionController::Parameters {
"authenticity_token"=>"~(省略),
"user"=>{"email"=>"test@test", "password"=>"ttttt1", "remember_me"=>"0"},
"commit"=>"Log in",
"controller"=>"devise/sessions",
"action"=>"create"
} permitted: false>
ちなみにuserコントローラーのshowアクションに飛んだときのparams。
ちゃんとidが飛んでいた。
4: def show
5: @user = User.find(params[:id])
=> 6: binding.pry
7: end
[1] pry(#<UsersController>)> params
=> <ActionController::Parameters {"controller"=>"users", "action"=>"show", "id"=>"2"} permitted: false>
ヘルパーは、誰が呼び出してるのか
結論:「sessionsコントローラーのcreateアクション」
次は、ヘルパーの呼び出しが気になった。
authenticate_user!とは異なり、
before_actionなどで、ヘルパーメソッドの呼び出しはしていない。
まずは、Gitでsessionsコントローラーのコードを見てみる。
devise/app/controllers/devise/sessions_controller.rb
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
最後行でafter_sign_in_path_forが呼び出されている。
つまり、sessionsコントローラーのcreateアクションを動かすと、
必ず呼ばれるメソッドだと解釈した。
そのため、before_actionのような呼び出しも不要だった。
感想
「ログイン後に、マイページへ遷移させたい」という機能は実装できたが、
devise側でどうなっているのか、については理解しきれなかった。
目的は達成したので、これ以上ここを掘り下げることに時間を使うべきではないが、
後々理解したいと思った。
特にRails側の機能であるrespond_with resourceとlocationオプション。
また、after_sign_in_path_forのオーバーライドと
deviseController、ApplicationControllerの関係性。
プラス、deviseコントローラーに定義されているhelper内の記述など。