[devise]現在ログインしているユーザ名が表示されない場合の解決策


環境

バージョン
ruby 2.6.5
rails 5.2.4.2
devise 4.7.1

目標

現在ログインしているユーザの名前を表示させたい。

問題

@yasuno0327氏が公開していたdevise にusername カラムを追加し、usernameを登録できるようにする。を参考にして実装したところ以下のようなエラーを吐いた。

Error
undefined method `username' for nil:NilClass

(意訳)
NilClassのnilオブジェクトに`username`メソッドは定義されてないよ

解決策

_current_username.html.erb
<% if user_signed_in? %>
  <!-- 変更前-->
  <%= @user.username %>
    <!-- 変更後-->
    <%= current_user.username %>
<% end %>

解決に至るまでに引っかかったこと

1.エラー文はどういう意味を指しているのか?

どうやら、@userがnilになっていることを指しているらしい。

参考

https://qiita.com/gonzaemon111/items/a6d9f3ad0645037125c2

2.@userがnilになっているのは何故?

インスタンス変数のスコープ外だから値が参照されない?
(正直、理解があやふやです。自分なりにかみ砕けたら、追記なり修正なり行います。)

[復習]各変数のスコープについて

種別 説明 文法
ローカル変数 それぞれのメソッドの中だけで存在しており、メソッドの処理が終了すると失われてしまう変数です。 通常の変数通り
インスタンス変数 インスタンスに属する変数で、インスタンスの中からであれば、どのメソッドからでも参照・変更できます。インスタンスごとに作られる変数ですので、インスタンスごとに違う値を保持しています。インスタンス生成後、最初に代入された時点で生成されますが、メソッド内でしか生成できませんので、注意が必要です。 変数名の前に「@」
クラス変数 クラスで共通の変数として生成されますので、同じクラスから生成されたインスタンスすべてで共通の値を持つことになります 変数名の前に「@@」
クラスインスタンス変数 クラスメソッドからのみアクセスできる変数で、メソッド内ではなく、クラス定義内に定義しなければいけません。クラスが定義されると同時に生成され、クラス変数同様、1つのクラスで共通の値を持っています 変数名の前に「@」

引用

https://web-camp.io/magazine/archives/15956

3.current_userと@userは何が違うのか?

メソッドか変数かの違い(...だと認識してます。)

current_user @user
deviseのヘルパーメソッド userのインスタンス変数