Forked from speed-of-light/application_controller.rb
Last active
March 4, 2024 09:07
-
-
Save itskingori/aae9a1905cec47f7fd52 to your computer and use it in GitHub Desktop.
How to handle exceptions like 401, 501, 404 in Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# As used with CanCan and Devise | |
class ApplicationController < ActionController::Base | |
protect_from_forgery | |
include ErrorResponseActions | |
rescue_from CanCan::AccessDenied, :with => :authorization_error | |
rescue_from ActiveRecord::RecordNotFound, :with => :resource_not_found | |
before_filter :authenticate! | |
private | |
def authenticate! | |
current_user || devise_controller? || ( authentication_error and return false ) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ErrorResponseActions | |
ERROR_RESPONSE_ACTIONS = %[authentication_error | |
authorization_error | |
resource_not_found | |
page_not_found | |
not_implmented | |
route_not_found | |
method_not_allowed].freeze | |
def authentication_error | |
respond_to do |format| | |
format.html do | |
flash[:error] = 'You are not logged in.' | |
session[:user_return_to] = request.fullpath | |
redirect_to new_user_session_path | |
end | |
# 401 Unauthorized response | |
format.any(:json, :xml){ request_http_basic_authentication 'My Application' } | |
end | |
end | |
def authorization_error | |
# 403 Forbidden response | |
respond_to do |format| | |
format.html{ render '/rescues/access_denied', :status => 403 } | |
format.xml{ render :xml => 'Access Denied', :status => 403 } | |
format.json{ render :json => 'Access Denied', :status => 403 } | |
end | |
end | |
def resource_not_found | |
respond_to do |format| | |
format.html{ render :template=>'/rescues/record_not_found', :status => 404 } | |
format.xml{ render :xml => 'Record Not Found', :status => 404 } | |
format.json{ render :json => 'Record Not Found', :status => 404 } | |
end | |
end | |
def page_not_found | |
respond_to do |format| | |
format.html{ render :template=>'/rescues/page_not_found', :status => 404 } | |
format.xml{ render :xml => 'Page Not Found', :status => 404 } | |
format.json{ render :json => 'Page Not Found', :status => 404 } | |
end | |
end | |
def not_implmented(allowed_methods) | |
method_not_allowed(allowed_methods, 'Not Implemented', 501) | |
end | |
def method_not_allowed(allowed_methods, message = 'Method Not Allowed', status=405) | |
response.headers['Allow'] ||= allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', ' | |
respond_to do |format| | |
format.html{ render :template=>'/rescues/method_not_allowed', :status => status } | |
format.xml{ render :xml => message, :status => status } | |
format.json{ render :json => message, :status => status } | |
end | |
end | |
def route_not_found | |
method, path = env['REQUEST_METHOD'].downcase.to_sym, env['PATH_INFO'] | |
# Route was not recognized. Try to find out why (maybe wrong verb). | |
allows = ActionDispatch::Routing::HTTP_METHODS.select { |verb| | |
begin | |
match = Rails.application.routes.recognize_path(path, :method => verb) | |
match[:action] != 'route_not_found' | |
rescue ActionController::RoutingError | |
nil | |
end | |
} | |
if !allows.empty? && !ActionDispatch::Routing::HTTP_METHODS.include?(method) | |
not_implmented allows | |
# raise ActionController::NotImplemented.new(*allows) | |
elsif !allows.empty? | |
method_not_allowed allows | |
# raise ActionController::MethodNotAllowed.new(*allows) | |
else | |
if Rails.configuration.consider_all_requests_local | |
response.headers['X-Cascade'] = 'pass' | |
render :nothing => true, :status => 404 | |
else | |
page_not_found | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rails.application.routes.draw do | |
# Catch-all to allow proper HTTP responses for 405 and 501 | |
match "*route_not_found.:format", :to => "application#route_not_found" | |
match "*route_not_found", :to => "application#route_not_found" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment