Edited at

【Rails】@current_user ||= User.find_by(id: session[:user_id])という書き方について


はじめに

Railsチュートリアル8章 8.2.2の意味がよくわからなかったので、自分なりにまとめてみる。概要としては、以下の通りだ。

@current_user = User.find_by(id: session[:user_id])で定義すると、@current_userを呼び出すたびにデータベースを検索することになる。つまり遅くなる。それを防ぐため、current_userメソッドを作成する。

def current_user

if session[:user_id]
@current_user ||= User.find_by(id: session[:user_id])
end
end

このような書き方はよく使うらしい。


実現したいこと

最初は@current_user = User.find_by(id: session[:user_id])でデータを取得する。

それ以降は、取得していた@current_user = { name: "Example User", .. }の値をそのまま流用する。


コードの分析


今までの書き方を使うと

if @current_user.nil?

@current_user = User.find_by(id: session[:user_id])
else
@current_user
end

最初(中身が何もないとき)だけ@current_userUser.find_by..を代入する。

それ以降は@current_userの中身があるのでそのまま@surrent_userを返す。


短く書くと

@current_user = @current_user || User.find_by(id: session[:user_id])

直訳すると、「@current_user@current_userまたはUser.find_by..である」だが、よくわからない。

||は項を左から順に判定していく。trueになった時点で処理が終了する。


1回目

@current_user =

@current_user # 最初の時点ではnilなのでfalse
||
User.find_by(id: session[:user_id]) # 中身があればtrueを返す


2回目以降

@current_user =

@current_user # @current_userに値が代入されているので、true
||
User.find_by(id: session[:user_id]) # 既にtrueの項があるので、これはスルーされる


さらに短く書くと

@current_user ||= User.find_by(id: session[:user_id])

a = a + 1a += 1で表すことができるのと同じ理論。


リンク