Ticket #9449: action_controller_exception_handler.diff
| File action_controller_exception_handler.diff, 5.3 kB (added by norbert, 1 year ago) |
|---|
-
actionpack/test/controller/rescue_test.rb
old new 3 3 uses_mocha 'rescue' do 4 4 5 5 class RescueController < ActionController::Base 6 class HandledException < StandardError 7 end 8 handle_exception HandledException, :with => :exception_handler 9 6 10 def raises 7 11 render :text => 'already rendered' 8 12 raise "don't panic!" … … 17 21 end 18 22 19 23 def missing_template; end 24 25 def handled_exception 26 raise HandledException 27 end 28 29 protected 30 def exception_handler 31 render :text => 'exception handled' 32 end 20 33 end 21 34 22 23 35 class RescueTest < Test::Unit::TestCase 24 36 FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze 25 37 … … 38 50 end 39 51 end 40 52 41 42 53 def test_rescue_action_locally_if_all_requests_local 43 54 @controller.expects(:local_request?).never 44 55 @controller.expects(:rescue_action_locally).with(@exception) … … 69 80 end 70 81 end 71 82 72 73 83 def test_rescue_action_in_public_with_error_file 74 84 with_rails_root FIXTURE_PUBLIC do 75 85 with_all_requests_local false do … … 93 103 assert_equal ' ', @response.body 94 104 end 95 105 96 97 106 def test_rescue_unknown_action_in_public_with_error_file 98 107 with_rails_root FIXTURE_PUBLIC do 99 108 with_all_requests_local false do … … 117 126 assert_equal ' ', @response.body 118 127 end 119 128 120 121 129 def test_rescue_missing_template_in_public 122 130 with_rails_root FIXTURE_PUBLIC do 123 131 with_all_requests_local true do … … 129 137 assert @response.body.include?('missing_template'), "Response should include the template name." 130 138 end 131 139 132 133 140 def test_rescue_action_locally 134 141 get :raises 135 142 assert_response :internal_server_error … … 138 145 assert @response.body.include?("don't panic"), "Response should include exception message." 139 146 end 140 147 141 142 148 def test_local_request_when_remote_addr_is_localhost 143 149 @controller.expects(:request).returns(@request).at_least_once 144 150 with_remote_addr '127.0.0.1' do … … 153 159 end 154 160 end 155 161 156 157 162 def test_rescue_responses 158 163 responses = ActionController::Base.rescue_responses 159 164 … … 182 187 assert_equal 'template_error', templates[ActionView::TemplateError.name] 183 188 end 184 189 185 186 190 def test_clean_backtrace 187 191 with_rails_root nil do 188 192 # No action if RAILS_ROOT isn't set. … … 217 221 assert_equal "GET, HEAD, PUT", @response.headers['Allow'] 218 222 end 219 223 224 def test_handled_exception 225 @controller.expects(:rescue_action).never 226 get :handled_exception 227 assert_response :success 228 assert_equal "exception handled", @response.body 229 end 230 220 231 protected 221 232 def with_all_requests_local(local = true) 222 233 old_local, ActionController::Base.consider_all_requests_local = -
actionpack/lib/action_controller/rescue.rb
old new 50 50 def process_with_exception(request, response, exception) 51 51 new.process(request, response, :rescue_action, exception) 52 52 end 53 54 # Handle exceptions raised in controller actions by passing at least one exception class and a :with option (as symbol or string) that contains the name of the method to be called to deal with the exception. 55 # 56 # class ApplicationController < ActionController::Base 57 # handle_exception User::NotAuthorized, :with => :not_authorized # self defined exception 58 # handle_exception ActiveRecord::RecordNotFound, :with => :not_found 59 # 60 # protected 61 # def not_authorized 62 # ... 63 # end 64 # 65 # def not_found 66 # ... 67 # end 68 # end 69 def handle_exception(*klasses) 70 options = klasses.extract_options! 71 unless handler = options[:with] 72 raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument." 73 end 74 75 klasses.each do |klass| 76 write_inheritable_hash(:handled_exceptions, klass => handler) 77 end 78 end 79 80 def exception_handler_for(klass) #:nodoc: 81 (read_inheritable_attribute(:handled_exceptions) || {})[klass] 82 end 53 83 end 54 84 55 85 protected … … 86 116 end 87 117 end 88 118 89 90 119 # Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>). By 91 120 # default will call render_optional_error_file. Override this method to provide more user friendly error messages.s 92 121 def rescue_action_in_public(exception) #:doc: … … 132 161 def perform_action_with_rescue #:nodoc: 133 162 perform_action_without_rescue 134 163 rescue Exception => exception # errors from action performed 135 rescue_action(exception)164 handle_exception_or_rescue_action(exception) 136 165 end 137 166 138 167 def rescues_path(template_name) … … 156 185 end 157 186 end 158 187 end 188 189 def handle_exception_or_rescue_action(exception) 190 if handler = self.class.exception_handler_for(exception.class) 191 send(handler) 192 else 193 rescue_action(exception) 194 end 195 end 159 196 end 160 197 end