11月からRailsを実務で使うことが決まったので、これから学習したことを備忘録に残していきます。
今日は【before_action】について。
▼ 参考にさせていただいた記事
pikawaka 【Rails】 before_actionの使い方とオプションについて
before_actionとは
コントローラの各アクションが実行される前に、何らかの処理を行いたい時に使用するもの。
フィルタの一つ。フィルタとは、コントローラにあるアクションの直前や直後、または直前と直後の両方に実行されるメソッドのことをいい、Railsには様々なフィルタが用意されている。
class UsersController < ApplicationController
before_action :メソッド名
end
これをコントローラーファイルの上部に記述しておくことで、コントローラーのアクションが動く前にメソッドが実行されて、そのあとでアクションが実行されるようになる。
どんな場合に、アクションが動く前にメソッドが実行されることが必要?
①ログイン認証時
before_action :authenticate_user!
authenticate_user!は、ログインしていない場合にログインページにリダイレクトさせてくれる、ヘルパーメソッド(Railsが元々用意してくれているメソッド)。便利ですね。
②重複した記述をまとめたい時
class MessagesController < ApplicationController
def index
@messages = Message.all
end
def show
@message = Message.find(params[:id]) # 同じ
end
def new
@message = Message.new
end
def create
Message.create(message_params)
end
def edit
@message = Message.find(params[:id]) # 同じ
end
def update
message = Message.find(params[:id])
message.update(message_parmas)
end
def destroy
message = Message.find(params[:id])
message.destroy
end
end
例えば、上記のようにshowアクションとeditアクションで全く同じ記述をしているとします。
Railsでは重複をなるべくさせない原則があるため、重複箇所をメソッド化してまとめてしまいましょう。
def find_message
@message = Message.find(params[:id])
end
このようにメソッドを定義したら、あとはbefore_actionに書くだけです。
class MessagesController < ApplicationController
before_action :find_message
def index
@message = Message.all
end
def show
end
def new
@message = Message.new
end
def create
Message.create(hoge_params)
end
def edit
end
def update
message = Message.find(params[:id])
message.update(hoge_parmas)
end
def destroy
message = Message.find(params[:id])
message.destroy
end
private
def set_message
@message = Message.find(params[:id])
end
end
今回の例では、find_messageメソッドはshowアクションとeditアクションでしか必要がないので、
以下のようにbefore_actionにオプションをつけます。
before_action :set_message, only: [:show, :edit]
オプションには他にもexceptやif、unlessなど色々ありますが、ここでは自分が一番使いそうなものだけ書いておきました。
補足
この記事の最初に「authenticate_user!」について書きましたが、
「authenticate_user!」の記述先であるApplicationControllerは、
全てのコントローラーが継承しているため、全てのコントローラーで働いてしまいます。
もし一部のコントローラーでbefore_actionが動いて欲しくない時があれば、
class HogesController < ApplicationController
skip_before_action :hogehoge
end
このようにskip_before_actionというメソッドを使いましょう。