平々凡々エンジニア

平凡で難しい悩みを解決

redirect_to url and return ってなんだろうか

railsチュートリアル リスト11.40から引用

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

上記のコードが行なっていることはなんとくわかるのですがand returnが何をしているのか詳しく理解できたいなかったので調べてみることにしました。

まずはand returnから調べていきます。

参考資料:2.2.14 二重レンダリングエラー

"Can only render or redirect once per action" 例

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

上記の例では"Can only render or redirect once per action" エラーになってしまいます。理由として 例えば@book.special?がtrueの場合、レンダリングを開始し、@book変数をspecial_showビューに転送します。 しかし、showアクションのコードはそこでは止まりません。showアクションのコードは最終行まで実行され regular_showビューのレンダリングを行おうとします。ここでエラーが出力されます。1つのコード実行パス内では、renderメソッドやredirectメソッドの実行は1度だけにしなければなりません。ですので明示的にreturnが必要にな ります。修正したコードを以下に示します。

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

ここでrender action: "special_show"とreturnを一行にして可読性をあげるためにandを使います。 修正したコードを以下に示します。

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

&&を使用すると評価の優先順位が高くてうまく機能しないため注意です。(優先順位参考資料) またrender の戻り値がtureの以外の場合はreturnは実行されないのも注意です。

ここまでrenderの話でしたがredirect_toでも同じようにredirect_toを行なっても即時にメソッドが中断され ることはないので上記のようにand returnを使用します。