Skip to content

Instantly share code, notes, and snippets.

@jhjguxin
Created August 13, 2012 05:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jhjguxin/3337130 to your computer and use it in GitHub Desktop.
Save jhjguxin/3337130 to your computer and use it in GitHub Desktop.
exception catch on rails 3(eg, 400, 403, 500), base on BBTangCMS
<div id="error_page" class="box">
<h1>Ops, 404</h1>
<p>
似乎没有这个页面哦!大哥,去看看别的吧。
</p>
</div>
<!--因为不排除连rails 都无法运行的情况 所以添加 'public/STATUS.htm' 还是很有必要的-->
<!--more>
Finally, the default exceptions application used by Rails that simply renders a page in `public/STATUS.html` is available here: [action_dispatch/middleware/public_exceptions.rb](https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/public_exceptions.rb)
Remember that whatever you do in the errors controller, it should not be anything “fancy”. Keep it simple because something already went wrong with your application!
</more-->
# encoding: utf-8
require File.expand_path('../boot', __FILE__)
require 'rails/all'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module BBTangCMS
class Application < Rails::Application
config.generators do |g|
g.orm :active_record
end
config.exceptions_app = self.routes
# 404 catch all route
#config.after_initialize do |app|
# app.routes.append{ match '*a', :to => 'application#render_404' } unless config.consider_all_requests_local
#end
end
end
class ErrorsController < ApplicationController
skip_before_filter :authenticate_user!
skip_authorization_check :only => [:render_404, :render_500]
def render_403
respond_to do |format|
format.html { render template: 'errors/403', layout: 'layouts/application', status: 403 }
#format.all { render nothing: true, status: 404 }
end
end
def render_404
respond_to do |format|
format.html { render template: 'errors/404', layout: 'layouts/application', status: 404 }
#format.all { render nothing: true, status: 404 }
end
end
def render_422
respond_to do |format|
format.html { render template: 'errors/422', layout: 'layouts/application', status: 422 }
#format.all { render nothing: true, status: 404 }
end
end
def render_500
respond_to do |format|
format.html { render template: 'errors/500', layout: 'layouts/application', status: 500 }
#format.all { render nothing: true, status: 500}
end
end
end
  1. Can no longer rescue_from ActionController::RoutingError
  2. My five favorite “hidden” features in Rails 3.2
  3. Rails 3.0 rescue from Routing Error Solution
  4. Rails 3.1 - Adding custom 404 and 500 error pages

When Rails 3.0 came out, one of the features that people suddenly missed was the ability to better handle exceptions. The issue was: since Rails 3 became a lot more Rack “fluent”, we had to move some features to the middleware stack and this forced us to move the whole exceptions handling as well. Rails 3.2 attempts to bring some customization back to the game by allowing you to set your own exceptions rack application that is invoked when a failure happens. For instance, you could set the exceptions application to your own router in your config/application.rb:

  config.exceptions_app = self.routes

Now, every time there is an exception, your router is going to be invoked. Therefore, to render custom 404 pages, you could simply add to your router:

  match "/404", :to => "errors#not_found"

And implement the logic in the controller as you wish! However, there are a few things to keep in mind if you go down this road:

  1. You need to use match in your routes and not get/post/put/delete because such exceptions can happen in any HTTP request;
  2. You won’t be able to see your custom exceptions in development unless you set config.consider_all_requests_local to false in your config/environments/development.rb. The reason is, if the request is considered local, Rails will always favor to show the debug exceptions page;
  3. You can always access the original exception in the controller at env["action_dispatch.exception"];
  4. It is not possible to set cookies, the session nor the flash after an exception happens. They all were already serialized back to the client;
  5. Finally, the default exceptions application used by Rails that simply renders a page in public/STATUS.html is available here: action_dispatch/middleware/public_exceptions.rb Remember that whatever you do in the errors controller, it should not be anything “fancy”. Keep it simple because something already went wrong with your application!
BBTangCMS::Application.routes.draw do
# 404 catch all route
unless BBTangCMS::Application.config.consider_all_requests_local
match '/403', :to => 'errors#render_403'
match '/404', :to => 'errors#render_404'
match '/422', :to => 'errors#render_422'
match '/500', :to => 'errors#render_500'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment