🚒

rescue_fromに助けてもらうには

2025/01/12に公開

状況

  • 当初コード
def set_article
  @article = Article.find(params[:id])
rescue ActiveRecord::RecordNotFound
  redirect_to articles_path, flash: { error: '記事が見つかりません' }
end
  • 上記コードに対して、
    「"rescue_from ActiveRecord::RecordNotFound, with: :handle_record_not_found" とかで
    "ActiveRecord::RecordNotFound" を親元のクラスにハンドリングし継承すべき」とアドバイスをいただきました。
  • これを機にrails apiで発生した例外をメソッド毎ではなく、定義と継承によって一括で処理することを学んだので、記載したいと思います。

学び

  • 例外が発生したらその親元のクラスのbase_controller.rb に
    = set_articleメソッドをArticlesControllerに残しつつ、ActiveRecord::RecordNotFoundの例外をBaseControllerで共通処理としてハンドリングする。
rescue_from ActiveRecord::RecordNotFound, with: :handle_record_not_found

private

def handle_record_not_found
 ここに共通化した処理をかく
end

具体例

1.BaseControllerに共通の例外処理を追加 :

  • rescue_from ActiveRecord::RecordNotFoundを使用して、例外が発生したときに共通の処理を実施
class BaseController < ApplicationController

  rescue_from ActiveRecord::RecordNotFound, with: :handle_record_not_found

  private

  def handle_record_not_found
    redirect_to top_path, flash: { error: 'この操作は実行できません' }
  end
end

2.set_articleメソッドの修正:

  • set_articleメソッドからrescueブロックを削除し、例外はBaseControllerで処理されるように
class ArticlesController < BaseController
  before_action :set_article, only: [:edit, :update]
  
  private

  def set_article
    @article = Article.find(params[:id])
  end
end

所見

  • set_articleメソッドをArticlesControllerに残しつつ、
    BaseControllerを継承するすべてのコントローラーで例外処理を共通化することができるように
    = コードの重複を避けることができる。
  • わかりやすい記事を記載されている方がいらっしゃりましたので、参考に載せさせていただきます。

https://zenn.dev/soramarjr/articles/2388dec7fa65a1

Discussion