ux00ffの日記

2012-01-25

Rails 3.1.3 でグローバルエラーハンドリングをする方法(自分ルール)

結論からすれば正しいものがよくわからない。残念。

世間的には Controller でrescue_action_in_public をオーバーライドせよ。production 環境で動作させ、ローカルからではないように見えるアクセスであればうまく動作するであろう。ということなのだが、試行錯誤してみたものの手元のローカル環境、VM上ともにうまく動作しなかった。みんな問題なくでけてんのかなぁ。

仕方がないので、自分なりにやり方を決めることにする。

まず、

However, things are a little different in Rails 3. The reality is, as of Rails 3.0.1, ApplicationController can't catch ActionController::RoutingError and thus, we cannot take advantage of rescue_from like we used to.


とのことなので、ルーティングエラーは「エラー」としてコントローラが取り扱うものではなくなったようだ。
(これは理にかなっていると思う。ルーティングエラーはコントローラに処理をマッピングされる前の段階だから。)

ルーティングエラー(404系)に関しては、route.rb で対応することにして、

  • config/route.rb
  #.. ルート定義の最後に、全ての指定にマッチするルーティング定義を置いておく。
  match '*path',:to=>'application#error404'

ここで指定した error404 を含むエラーハンドリング用のモジュールを一つ用意し、ApplicationController など上位のController クラスで include してやることにする。

  • app/controller/error_handling.rb
module ErrorHandling
  def self.included(mod)
    mod.instance_eval do
      # rescue_from Exception で全ての例外に対してハンドラを登録する
      rescue_from Exception ,:with=>:handle_error
    end
  end

  # 
  # エラー処理を行うハンドラ。
  # ApplicationController でこのモジュールをインクルードしている場合、
  # 実際の処理はサブクラス(ApplicationController自身も含む)でオーバーライドできる。
  #
  def handle_error(e=nil)
    case e
    when Application404Exception
      error404
      return
    end

    raise e
  end

  #
  # 404 エラーを表示するメソッド
  # ルーティングエラー時の他、Application404Exception でもハンドリングされる。
  #
  def error404
    url = request.url 
    render :text=>"<h1>404 not found</h1><br>(#{url})", :status=>404
  end
end

#
# アプリケーションで404 を発生させる例外。
#
class Application404Exception <Exception
end

これで、ルーティングエラーの他、アプリケーションで発生する各種の例外に対する統一的なハンドラを作成することができた。しかし、常道から外れた感じ満々なので、後でちゃんと調べる。

参考にした記事とか

http://d.hatena.ne.jp/Climber/20100527/1274942772

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/ux00ff/20120125/1327504931
リンク元