This page looks best with JavaScript enabled

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

 ·   ·  ☕ 2 分で読めます
✏️

はじめに

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

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

1
2
3
4
5
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", .. }の値をそのまま流用する。

コードの分析

今までの書き方を使うと

1
2
3
4
5
if @current_user.nil?
  @current_user = User.find_by(id: session[:user_id])
else
  @current_user
end

最初(中身が何もないとき)だけ@current_userUser.find_by..を代入する。
それ以降は@current_userの中身があるのでそのまま@current_userを返す。

短く書くと

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

直訳すると、「@current_user@current_userまたはUser.find_by..である」だが、これだけではよくわからないので、処理の流れとして捉える。
||は項を左から順に判定し、trueになった時点で処理が終了するので、以下のようになる。

1回目

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

2回目以降

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

さらに短く書くと

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

a = a + 1a += 1で表すことができるのと同じ理論(厳密には違うらしいが)。

リンク

Share on

END
END
@aiandrox

目次