Ruby on Railsのコールバックは、コントローラーのアクションが実行される前後に自動的に処理を挟み込む仕組みです。認証チェック、ログ記録、データの事前読み込みなど、複数のアクションで共通する処理をコールバックとして定義することで、コードの重複を防ぎメンテナンス性を向上させます。この記事では、コールバックの種類と実践的な使い方を解説します。
基本的な使い方
最もよく使われるのがbefore_actionです。アクションが実行される前に指定したメソッドを自動的に呼び出します。
class PostsController < ApplicationController
before_action :set_message
def index
# @messageはset_messageで既に設定済み
end
def show
# @messageはset_messageで既に設定済み
end
private
def set_message
@message = "ようこそ"
end
endbefore_action :set_messageと記述すると、このコントローラーのすべてのアクションが実行される前にset_messageメソッドが呼ばれます。認証チェックやデータの事前読み込みに頻繁に使用されるパターンです。
コールバックの種類
Railsのコントローラーには3種類のコールバックがあります。
| コールバック | 実行タイミング | 主な用途 |
|---|---|---|
| before_action | アクション実行前 | 認証、データの事前読み込み |
| after_action | アクション実行後 | ログ記録、レスポンスの後処理 |
| around_action | アクション実行の前後 | 処理時間の計測、トランザクション管理 |
特定のアクションに限定する
onlyオプションやexceptオプションを使って、コールバックを適用するアクションを制限できます。
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
@posts = Post.all
end
def show
# @postはset_postで設定済み
end
def edit
# @postはset_postで設定済み
end
def update
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
def destroy
@post.destroy
redirect_to posts_path
end
private
def set_post
@post = Post.find(params[:id])
end
def authenticate_user!
redirect_to login_path unless current_user
end
endonlyは指定したアクションでのみ実行し、exceptは指定したアクション以外で実行します。上記の例では、indexとshowは認証不要で、それ以外のアクションには認証が必要です。
after_actionの使い方
after_actionはアクションの実行後に処理を行います。ログの記録やレスポンスヘッダーの追加などに使います。
class ApplicationController < ActionController::Base
after_action :log_access
private
def log_access
Rails.logger.info "#{controller_name}##{action_name} accessed by #{current_user&.name || 'Guest'}"
end
endaround_actionの使い方
around_actionはアクションの前後を包み込むように処理を実行します。yieldでアクション本体を実行します。
class ReportsController < ApplicationController
around_action :measure_time, only: [:generate]
def generate
@report = Report.create_monthly_report
end
private
def measure_time
start_time = Time.current
yield # ここでアクション本体が実行される
duration = Time.current - start_time
Rails.logger.info "処理時間: #{duration}秒"
end
endbefore_actionでredirect_toやrenderを実行すると、後続のアクション本体はスキップされます。これを利用して認証チェックを実装すると、未認証のユーザーがアクションを実行するのを防げます。
コールバックを多用しすぎると、処理の流れが追いにくくなります。コールバックチェーンが長くなる場合は、Service Objectなどのデザインパターンを検討してください。
まとめ
before_actionはアクション実行前、after_actionは実行後、around_actionは前後に処理を挟むonlyとexceptで適用するアクションを制限できる- 認証チェックやデータの事前読み込みは
before_actionの代表的な使い方 around_action内ではyieldでアクション本体を実行するbefore_action内でredirect_toするとアクション本体はスキップされる- コールバックの多用は避け、処理の流れを追いやすく保つ