27
11

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 5 years have passed since last update.

素人による "and return unless"

Last updated at Posted at 2019-08-20

Railsチュートリアル11章リスト11.40にて

 以下のコードがあった。

  def show
    @user = User.find(params[:id])
    redirect_to root_url and return unless @user.activated?
  end

 このコードの中のand return unlessの挙動が分からなかったので、調べて考えたことをまとめておく。

and returnについて

 まずはand returnについて見てみよう。Railsガイドにて以下の解説と参考コードがあった。

Rails開発をやっていれば、一度は "Can only render or redirect once per action" エラーに遭遇したことがあるでしょう。いまいましいエラーですが、修正は比較的簡単です。このエラーはほとんどの場合、開発者がrenderメソッドの基本的な動作を誤って理解していることが原因です。

def show
  @book = Book.find(params[:id])
  if @book.special?
    render action: "special_show"
  end
  render action: "regular_show"
end

 上のコードでは、@book.special?trueの時、if文内のrenderとその外のrenderも実行されてしまい、二重レンダリングというエラーになる。そこで、and returnを使って明示的にメソッドを抜けることで二重レンダリングを避ける。

def show
  @book = Book.find(params[:id])
  if @book.special?
    render action: "special_show" and return
  end
  render action: "regular_show"
end

 挙動としては、renderredirect_toの戻り値がtrueなので、andの後ろのreturnが実行されるということだ。

 なお、&& returnを使うとこの場合正しく動作しない。というのも、&&は優先度が高いのでrender action: ("special_show" && return)ということになるからだろう。一方のandの優先度は超低い。and returnはこのandの優先度の低さを上手に利用している。

and return unlessについて

 and returnの働きとandの優先度について書いたので、あとはそれを組み合わせるだけだ。もう一度最初のコードを見てみよう。

  def show
    @user = User.find(params[:id])
    redirect_to root_url and return unless @user.activated?
  end

 andの優先順位は低いので、redirect_to root_urlが先に評価されるので、andが評価するのはredirect_to root_urlreturnになる。()でくくってやると以下のようになる。

(redirect_to root_url) and (return)

あとは、上のカタマリがunlessの後置修飾がついているだけだ。つまり、redirect_to root_url and return unless @user.activated?は以下と同じになる。

unless @user.activated?
  redirect_to root_url and return
end

おわり

 and return unlessというカタマリで見てしまったので挙動が見えず分からなくなってしまったが、ひとつずつ分解して見てみるとそこまで恐ろしいものでもなかった。「巨大で恐ろしい相手でも、ひとつひとつは取るに足らないものだぞ」と人生の教訓をプログラミングが教えてくれた。

27
11
4

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
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?