Railsで転職活動用のポートフォリオ作成中です。
deviseのuser_signed_in?
メソッドが正常に動作しない不具合が発生しました。
不具合詳細
確かにログインできているのに、user_signed_in?
が常にfalse
を返す。
...
8: <% binding.pry %>
=> 9: <% if user_signed_in? %>
10: <p>ユーザー詳細です。</p>
11: <p><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></p>
12: <% end %>
...
$ user_signed_in?
=> false
前提事項
・macOS Monterey v12.1
・ruby v3.0.3
・Rails v6.1.4.4
・devise 4.8.1
その他
・自作のユーザー認証機能のdeviseへの置き換え途中に発生したエラー
・自作の認証機能は、ほぼRailsチュートリアルのコピー
原因
自作のcurrent_user
メソッドがsessions_helper
に残っており、その実行結果(nil)をuser_signed_in?
メソッドが参照してfalseを返していた。
参考(英語):
対策
以下のcurrent_user
メソッドを削除(コメントアウト)する。
(Railsチュートリアルを参考にしてきた場合は、おそらくsessions_helperに記載がある。)
before
module SessionsHelper
...
# 記憶トークンcookieに対応するユーザーを返す
def current_user
if (user_id = session[:user_id])
@current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user&.authenticated?(:remember, cookies[:remember_token])
log_in user
@current_user = user
end
end
end
...
end
after
module SessionsHelper
...
# 記憶トークンcookieに対応するユーザーを返す
# def current_user
# if (user_id = session[:user_id])
# @current_user ||= User.find_by(id: user_id)
# elsif (user_id = cookies.signed[:user_id])
# user = User.find_by(id: user_id)
# if user&.authenticated?(:remember, cookies[:remember_token])
# log_in user
# @current_user = user
# end
# end
# end
...
end
考察
なぜcurrent_user
のコメントアウトのみでuser_signed_in
の不具合も改善されたのか。
特にdeviseメソッドの中身を調べたわけではないので予想に過ぎませんが、diviseのuser_signed_in
メソッドはcurrent_user
メソッドの実行結果を参照しているのでなないでしょうか。
今回発生した不具合に関係する処理の中にcurrent_user
はありませんでした。しかし、自作のcurrent_user
が実行され、中身を見てみたところnil
が入っていました。
...
13: def current_user
14: if (user_id = session[:user_id])
15: @current_user ||= User.find_by(id: user_id)
16: elsif (user_id = cookies.signed[:user_id])
17: user = User.find_by(id: user_id)
18: if user&.authenticated?(:remember, cookies[:remember_token])
19: log_in user
20: @current_user = user
21: end
22: end
23: binding.pry
=> 24: end
[1] pry(#<UsersController>)> current_user
=> nil
user_signed_in
メソッドが、「current_user
の中身がnil
ならユーザーはログインしていないだろう」と判断していた説。
まとめ
同じ名前のメソッドには要注意。