非効率なメモ化の改善

Railsでは、よく以下のようなコードを書いたり見たりする。メモ化って言うらしい。

def current_user
  @current_user ||= User.find_by(cookies.signed[:user_id])
end

#current_userが呼ばれるまではDBへのアクセスは発生しない。そして、アクセスした結果を@current_userに代入しておくことで、2回目以降の呼び出しではDBへのアクセスが発生しないようになっている。

割とよく書きがちなこのコードだけど、非効率なケースがある。DBから取得した結果がnilのケースだ。このケースだと、@current_usernilのままなので#current_userが呼び出されるたびにDBに再度アクセスすることになる。

DBにアクセスした結果nilだとわかっているなら、2回目以降はDBにアクセスしなくていいだろう。というわけで、こんな感じで直す。

def current_user
  return nil if @current_user_exists == false
  @current_user ||= User.find_by(cookies.signed[:user_id])
  @current_user_exists ||= !@current_user.nil?
  @current_user
end

以前のものとは見栄えが悪くなったけど、より効率的になった。もっとシンプルに書けそうな気はしている。