27
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-01-25

はじめに

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の中身があるのでそのまま@current_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で表すことができるのと同じ理論(厳密には違うらしいが)。

リンク

27
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?