ログイン機能のアプリ作った際に、app/helpers/sessions_helper.rb
ファイルに以下のメソッドを定義しました。
module SessionsHelper
def current_user
@current_user ||@current_user = User.find_by(id: session[:user_id])
end
def logged_in?
current_user.present?
end
end
メソッドが呼び出されているviewファイル(app/views/layouts/application.html.erb)
<% if logged_in? %>
<%= link_to "Profile", user_path(current_user.id) %>
<%= link_to "Logout", session_path(current_user.id), method: :delete %>
<% else %>
<%= link_to "Sign up", new_user_path %>
<%= link_to "Login", new_session_path %>
<% end %>
私はcurrent_userメソッドの@current_user
がなぜインスタンス変数で定義されているかが分かりませんでした。current_user
で定義したとしてもエラー等がなく、アプリは動きます。
しかし、メンターさん等の助けがあって、なぜ@current_user
にしているか理由がわかりました。以下が詳細な説明になっています。
インスタンス変数とは
class A
def b
@a = 1
end
def c
@a
end
end
a = A.new
p a.b
p a.c
# 結果 @aが値を保持しています。
1
1
上記のような変数です。
app/helpers/sessions_helper.rbファイルのcurrent_user
メソッド内の式を説明します。
def current_user
@current_user ||@current_user = User.find_by(id: session[:user_id])
end
上記の式は@current_user
の中に値がなかった場合、User.find_by(id: session[:user_id])
が実行されて、その結果が@current_user
に入ります。
しかし@current_user
の中に値があった場合は、User.find_by(id: session[:user_id])
は実行しません。
今回のケースはapp/views/layouts/application.html.erbファイルの中で、current_user
メソッドが2回呼び出されています。インスタンス変数は値を保持することができるため、1回目で呼び出された時に、@current_user = User.find_by(id: session[:user_id])
が行われ、2回目呼び出された時は、@current_user
が値を既に持っているので、この処理(User.find_by(id: session[:user_id])
)が行われません。
つまり、一回分処理が行われずに済んでいます。
ターミナル画面から確認しても処理が節約されている事がわかります。
app/helpers/sessions_helper.rbファイルで@current_user
を使った場合
Started GET "/" for ::1 at 2022-10-13 14:42:22 +0900
Processing by SessionsController#new as HTML
Rendering layout layouts/application.html.erb
Rendering sessions/new.html.erb within layouts/application
Rendered sessions/new.html.erb within layouts/application (Duration: 1.6ms | Allocations: 591)
[Webpacker] Everything's up-to-date. Nothing to do
Rendered shared/_header.html.erb (Duration: 0.1ms | Allocations: 39)
User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ app/helpers/sessions_helper.rb:3:in `current_user'
Rendered shared/_footer.html.erb (Duration: 0.2ms | Allocations: 38)
Rendered layout layouts/application.html.erb (Duration: 81.0ms | Allocations: 3952)
Completed 200 OK in 97ms (Views: 80.6ms | ActiveRecord: 1.4ms | Allocations: 4465)
sqlが一度しか実行されていません。