8
5

More than 3 years have passed since last update.

Rails controllerで早期returnするTips

Last updated at Posted at 2019-11-07

TL;DR

users_controller.rb
def show
  @user.do_something(params[:foo])

  my_redirect && return # 注目

  @user.do_something_other
end

private

def my_redirect
  if @user.some_flag?
    redirect_to some_path(@user.some_attr)
  end
end

解説

以下の要望があると考えましょう、@user.do_something(params[:foo])で、paramの一部を処理してから、@user.some_flag?を判断して、some_path(@user.some_attr)に動的リダイレクトしたいです。
また、リダイレクトが実行された場合、@user.do_something_otherを実行しないことです。
特にSEO系の要件でそういうリダイレクト処理が多いと思いますね。

Guard Clauseとは

条件分岐や関数の途中、早期に脱出する手段の一つです。積極的に使うと、ソースコードの可読性が向上し、性能もアップすることが期待されています。「ガード節」、「早期復帰」など和訳があります。
Rubyの場合、Guard Clauseはループ途中のnextbreak、あるいはメソッド途中明記的なreturnなどがあります。

まずは正攻法

users_controller.rb
def show
  @user.do_something(params[:foo])
  redirect_to some_path(@user.some_attr) && return if @user.some_flag?

  @user.do_something_other
end

リダイレクトの判断ロジックがシンプルで再利用する予定がない場合、正攻法は大体対応できます。
しかし複雑なロジックでリダイレクトを組む場合、コントローラーが肥大化になりがちです。

今までの王道

before_action に該当ロジックをHookさせると、Actionが実行する前の段階でリダイレクトが実行され、Actionの実行がSkipされます。
例として、devisebefore_action :authenticate_user!が有名です。

users_controller.rb
before_action :setup_user, only: :show
before_action :my_redirect, only: :show

def show
  @user.do_something_other
end

private

def setup_user
  @user.do_something(params[:foo])
end

def my_redirect
  if @user.some_flag?
    redirect_to some_path(@user.some_attr)
  end
end

ご覧のように、before_actionで対応する場合、リダイレクトがActionが実行する前の段階で実行されるので、@user.do_something(params[:foo])before_actionに出さなければいけません。
修正範囲が広くなり、ロジックが複雑な場合、返って不便になります。

今回紹介したい手法

users_controller.rb
def show
  @user.do_something(params[:foo])

  my_redirect && return # 注目

  @user.do_something_other
end

private

def my_redirect
  if @user.some_flag?
    redirect_to some_path(@user.some_attr)
  end
end

原理

まずmy_redirectは、@user.do_something(params[:foo])で実行されます。

次に@user.some_flag?falseの場合、nilが返されて、my_redirect && return短絡評価の影響で飛ばされ、以降の処理が続かれます。

@user.some_flag?trueの場合、下記の内容が返されて、truthyなので、&& returnが実行され、メソッドが脱出され、以降のロジックが実行されません。

Redirected to http://localhost:3000/some_path?foo=bar
"<html><body>You are being <a href=\"http://localhost:3000/some_path?foo=bar\">redirected</a>.</body></html>"

以上でした。

参考

8
5
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
8
5