Ruby On Rails入門。ControllerのCallbackメソッド。before_action, after_action

 

突然ですが、Railsのbefore_action, after_actionってご存知でしょうか?

知らない方はこの記事を機に覚えて頂ければ良いと思うのですが、RailsではController 内でbefore_actionやafter_actionというメソッドのActionの前後にフィルターを 差し込むことができます。

今回はそんなbefore_action, after_actionに関する記事です。

 

before, afterアクションの宣言の仕方

 

Controllerでのコールバックメソッドの宣言方法は次のような形です。

class BlogsController < ApplicationController
  before_action :set_blog, only: %i(new edit)

  def index
  end

  def new
  end

  def edit
  end

  def create
  end

  # ~(略) ~

  def set_blog
    @blog = Blog.find(params[:id])
  end
end

この例では、new,editアクションの前にset_blogというインスタンス変数を格納 するメソッドを実行せよという意味になります。

基本的には

before_action [メソッド名]

のような形でaction前に実行するメソッドを指定する形になります。 反対にafter_actionの場合はactionの処理がすんだ後に実行されます。

 

after/before_action以外のコールバックメソッド

 

controllerのコールバックメソッドを羅列すると,

  • before_action
  • around_action
  • after_action
  • prepend_before_action
  • prepend_around_action
  • prepend_after_action
  • append_before_action
  • append_around_action
  • append_after_action
これだけあります。before/actionはもともと紹介していましたが、aroundはアクションの 前後で実行するメソッドになります。さらにprependはbefore_actionより前の処理、append はafter_actionより後の処理ということになります。

こうやって書くと、before_action/after_actionはcontrollerに一つしかけないのでは? と考えてしまう方もいるかもしれませんがそんなことはありません。ちゃんと宣言順序に実行されるので実行順に宣言してあげれば大丈夫です。

def HogeController < ApplicationController
  before_action :method_a
  before_action :method_b
  before_action :method_c
  before_cation :method_d
end

このように書いた場合はアルファベット順(上にあるものから)実行されていきます。

 

条件付きコールバック、only,except,ifオプション

 

before_action, after_actionもrailsのほかのメソッドのご多聞にもれずオプションをもっています。

def HogeController < ApplicationController
  before_action :method_a, only: [ :new, :edit]
end

このようにonlyオプションを使って書いた場合method_aはnew, editアクションの前にだけ実行されます。exceptオプションは逆で指定したアクション以外ではbefore_actionを実行する形になります。

また、ifオプションはラムダを渡すことによって式がtrueになった場合だけ実行させることもできます。(unlessオプションはtrue以外の時に実行される)

def HogeController < ApplicationController
  # current_user.editable?がtrueの時に           
  method_aを実行 before_action :method_a, if: -> { current_user.editable? }
end

 

どういうところで使うの?

 

単にbefore_actionなどを説明されたところで実務レベルでどういうところでどこで使っていいかわからないですよね。記事を書いていてそんなことに気づいたので簡単に紹介すると

多くのRailsユーザがしようしているdeviseなどを使うとよくbefore_actionでユーザがそのページへのアクセス権限があるかどうかというのをチェックするためにbefore_actionを使います。

deviseの場合authenticateuser!というのをbeforeactionにセットすることで認証済みのユーザかどうかをチェックすることができます。

def HogeController < ApplicationController
  before_action :authenticate_user!
end

 

ただ、

「よし!じゃあ認証が必要なページ全てにbefore_action :authenticate_user!を入れればいいんだ!」

とはならないでください。rubyには継承という機能があるので,MypageControllerのようなものを設けて、認証が必要なコントローラはそれを継承して使うやり方が良いです。

# before_actionでユーザを認証するコントローラを作成
def MypageController < ApplicationController
  before_action :authenticate_user!
end

# 上で作成したコントローラであるMypageControllerを継承する形で
# 認証が必要なコントローラを実装する。
def Mypage::SettingsController < MypageController
end

 

まとめ

 

下記、コントローラのまとめです。

  • before/after_actionはControllerのアクションの前後に処理を差し込める
  • before/after_action以外にも様々なコールバックがある(あまり使わない?)
  • only, except, if, unlessオプションを使うことで条件つきでコールバックを実行可能
  • 認証が必要なControllerでbefore_actionを使ったりする
 

今回はControllerのコールバック関数について割と詳細に説明しましたが、before_actionなどを使うと同じController内の共通処理をDRYなコードで書くことができます。先に説明した認証の処理のように「ユーザがログイン済みか」「結果によりリダイレクトを行う」などの処理はアクション共通の処理ですがbefore_actionをしらないと各アクションにそれぞれの処理を書いたりといった重複の多いコードを書いてしまう 可能性があります。

Railsを学ぶ際は、MVCそれぞれの基本的な役割をみにつけるのもそうですがこういった小技的な知識もコツコツと身につけていきましょう。こういった細かい知識を知っているのと知っていないのでコードを簡潔に保てるので合間時間でもよいのでこういった知識も収集することをオススメします。