その rescue_from ほんとに必要ですか

だいたい必要ないと思ってますよ、という話。


Rails アプリケーションの開発において rescue_from を追加することが正しいことは少ないと思っています。
rescue_from とは実際にはアクションおよびコントローラをまたいだ begin - rescue ( try - catch )であると言えます。
begin - rescue は大きく分けて2種類の使い方があると思っています。1つは、局所的な例外処理を書くとき。もう1つが例外からの復帰を諦めた場合に最後に(最初に)囲んでおくやつです。
ここでは前者を「復帰用rescue」、後者を「覆い隠し用rescue」と呼びます1

class Foo
  def fetch
    AwesomeHTTP::Get("https://example.com")
  rescue AwesomeHTTP::Error => e # ライブラリのエラーを拾っておく
    # 「復帰用rescue」 ( 局所的な例外処理 )
    raise MyApp::APIError, e
  end
end

begin
  Foo.new.fetch
rescue MyApp::Error => e
  # 「覆い隠し用rescue」
  # 復帰できないときには MyApp::Error あるいはそのサブクラスを投げるという規約にしておく
  warn "エラーが発生しました"
  warn e
  exit 0
end

rescue_from はこの使い分けでいうと「覆い隠し用rescue」であると言えます。根拠は、どこで起きるかは関係なくすべて拾ってユーザー側には通知しないようにしている点です。

Rails にはある程度のエラー処理を自動的にやってくれる仕組みがあります。Rails guide の rescue_responses を参照してください。

Configuring Rails Applications — Ruby on Rails Guides

rescue_responses を使わずに rescue_from のブロックで何か動的に処理をしたくなっている時点で「復帰用rescue」に該当していると思います。
しかし、復帰時の方法は果たしてコントローラ単位で本当に共通なのでしょうか?どこで起きた例外かによって処理を変えたいのでは?

というわけで rescue_from を書いておいたほうがいいことってほっとんどないと思うんですけどどうなんですかね。 ただの500ページより情報量が多いエラーページを出すために ApplicationController に書いとく、とかはアリなのかなあ。


  1. よい名前、あるいはこれに該当する分け方が既にあったら教えてください :bow: