🦁

before_action地獄祭り

2025/03/26に公開

Daily Blogging95日目

みなさんはbefore_action使ってますか?
私は使っています
それはもう沢山(泣)

便利だよねbefore_action

Railsエンジニアにはお馴染みの機能だと思いますが、before_actionはデフォルトで用意されている便利な機能のことですね
https://railsdoc.com/page/before_action

たとえばこう使える

class UsersController < ApplicationController
  before_action :authenticate_user!

  def show
    @user = User.find(params[:id])
  end

  private

  def authenticate_user!
    redirect_to login_path, alert: 'Please log in.' unless current_user
  end
end

before_actionにメソッドを指定すると、コントローラのアクションを実行する前にそのメソッドを実行してくれる。

便利すぎてこうなる

便利なものも使いすぎるとコードの品質を下げることになる

class UsersController < ApplicationController
  before_action :authenticate_user!
  before_action :set_user
  before_action :check_admin
  before_action :correct_user
  before_action :log_access
  before_action :set_timezone
  before_action :check_subscription
  before_action :set_locale

  def show
  end

  private

  def authenticate_user!
    redirect_to login_path, alert: 'Please log in.' unless current_user
  end

  def set_user
    @user = User.find(params[:id])
  end

  def check_admin
    redirect_to root_path, alert: 'Access denied.' unless current_user&.admin?
  end

  def correct_user
    redirect_to root_path, alert: 'Not authorized.' unless @user == current_user
  end

  def log_access
    Rails.logger.info "User #{current_user.id} accessed show action."
  end

  def set_timezone
    Time.zone = current_user.timezone if current_user
  end

  def check_subscription
    redirect_to billing_path, alert: 'Subscription required.' unless current_user&.subscribed?
  end

  def set_locale
    I18n.locale = current_user&.locale || I18n.default_locale
  end
end

※AIにサンプルを作ってもらったので細かいところは間違ってるかも

つらみポイント

before_actionを使いすぎるとこういう悩みが出てくる

  • どこで何してるかわからない
  • アクションが一つしかないのにbefore_action用の処理が多すぎてメインのロジックに集中できない
  • 知らないところで知らないインスタンス変数が定義されている
  • before_actionを呼び出す順序が決まっている

この中でもインスタンス変数を定義している、順序が決まっているが特に辛い

使い方はちゃんと決めよう

何事もチームで取り決めがあるのであればそんな問題にはならない
before_actionは魔境になりやすいので、ちゃんと使い方を定義した方が良い

たとえば、

  • 認証チェックにしか使わない
  • 似た性質の処理は一つのbefore_actionにまとめる
  • インスタンス変数は定義しない

とかとか

Discussion