Changeset 7597
- Timestamp:
- 09/23/07 21:56:22 (10 months ago)
- Files:
-
- trunk/actionpack/CHANGELOG (modified) (1 diff)
- trunk/actionpack/lib/action_controller/rescue.rb (modified) (7 diffs)
- trunk/actionpack/test/controller/rescue_test.rb (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/actionpack/CHANGELOG
r7596 r7597 1 1 *SVN* 2 3 * Introduce ActionController::Base.rescue_from to declare exception-handling methods. Cleaner style than the case-heavy rescue_action_in_public. #9449 [norbert] 2 4 3 5 * Rename some RequestForgeryProtection methods. The class method is now #protect_from_forgery, and the default parameter is now 'authenticity_token'. [Rick] trunk/actionpack/lib/action_controller/rescue.rb
r7592 r7597 42 42 base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES 43 43 44 base.class_inheritable_hash :rescue_handlers 45 base.rescue_handlers = {} 46 44 47 base.extend(ClassMethods) 45 48 base.class_eval do … … 51 54 def process_with_exception(request, response, exception) 52 55 new.process(request, response, :rescue_action, exception) 56 end 57 58 # Rescue exceptions raised in controller actions by passing at least one exception class and a :with option that contains the name of the method to be called to respond to the exception. 59 # Handler methods that take one argument will be called with the exception, so that the exception can be inspected when dealing with it. 60 # 61 # class ApplicationController < ActionController::Base 62 # rescue_from User::NotAuthorized, :with => :deny_access # self defined exception 63 # rescue_from ActiveRecord::RecordInvalid, :with => :show_errors 64 # 65 # protected 66 # def deny_access 67 # ... 68 # end 69 # 70 # def show_errors(exception) 71 # exception.record.new_record? ? ... 72 # end 73 # end 74 def rescue_from(*klasses) 75 options = klasses.extract_options! 76 unless options.has_key?(:with) # allow nil 77 raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument." 78 end 79 80 klasses.each do |klass| 81 rescue_handlers[klass.name] = options[:with] 82 end 53 83 end 54 84 end … … 59 89 log_error(exception) if logger 60 90 erase_results if performed? 91 92 return if rescue_action_with_handler(exception) 61 93 62 94 # Let the exception alter the response if it wants. … … 88 120 end 89 121 90 91 122 # Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>). By 92 123 # default will call render_optional_error_file. Override this method to provide more user friendly error messages.s … … 98 129 # or just return headers if no such file exists. For example, if a 500 error is 99 130 # being handled Rails will first attempt to render the file at <tt>public/500.html</tt>. 100 # If the file doesn't exist, the body of the response will be left empty 131 # If the file doesn't exist, the body of the response will be left empty. 101 132 def render_optional_error_file(status_code) 102 133 status = interpret_status(status_code) … … 130 161 end 131 162 163 # Tries to rescue the exception by looking up and calling a registered handler. 164 def rescue_action_with_handler(exception) 165 if handler = handler_for_rescue(exception) 166 if handler.arity != 0 167 handler.call(exception) 168 else 169 handler.call 170 end 171 true # don't rely on the return value of the handler 172 end 173 end 174 132 175 private 133 176 def perform_action_with_rescue #:nodoc: … … 147 190 def response_code_for_rescue(exception) 148 191 rescue_responses[exception.class.name] 192 end 193 194 def handler_for_rescue(exception) 195 if handler = rescue_handlers[exception.class.name] 196 method(handler) 197 end 149 198 end 150 199 trunk/actionpack/test/controller/rescue_test.rb
r7181 r7597 4 4 5 5 class RescueController < ActionController::Base 6 class NotAuthorized < StandardError 7 end 8 9 class RecordInvalid < StandardError 10 end 11 12 rescue_from NotAuthorized, :with => :deny_access 13 rescue_from RecordInvalid, :with => :show_errors 14 6 15 def raises 7 16 render :text => 'already rendered' … … 16 25 raise ActionController::NotImplemented.new(:get, :put) 17 26 end 27 28 def not_authorized 29 raise NotAuthorized 30 end 31 32 def record_invalid 33 raise RecordInvalid 34 end 18 35 19 def missing_template; end 36 def missing_template 37 end 38 39 protected 40 def deny_access 41 head :forbidden 42 end 43 44 def show_errors(exception) 45 head :unprocessable_entity 46 end 20 47 end 21 22 48 23 49 class RescueTest < Test::Unit::TestCase … … 39 65 end 40 66 41 42 67 def test_rescue_action_locally_if_all_requests_local 43 68 @controller.expects(:local_request?).never … … 70 95 end 71 96 72 73 97 def test_rescue_action_in_public_with_error_file 74 98 with_rails_root FIXTURE_PUBLIC do … … 93 117 assert_equal ' ', @response.body 94 118 end 95 96 119 97 120 def test_rescue_unknown_action_in_public_with_error_file … … 117 140 assert_equal ' ', @response.body 118 141 end 119 120 142 121 143 def test_rescue_missing_template_in_public … … 130 152 end 131 153 132 133 154 def test_rescue_action_locally 134 155 get :raises … … 138 159 assert @response.body.include?("don't panic"), "Response should include exception message." 139 160 end 140 141 161 142 162 def test_local_request_when_remote_addr_is_localhost … … 153 173 end 154 174 end 155 156 175 157 176 def test_rescue_responses … … 183 202 end 184 203 185 186 204 def test_clean_backtrace 187 205 with_rails_root nil do … … 216 234 assert_response :method_not_allowed 217 235 assert_equal "GET, HEAD, PUT", @response.headers['Allow'] 236 end 237 238 def test_rescue_handler 239 get :not_authorized 240 assert_response :forbidden 241 end 242 243 def test_rescue_handler_with_argument 244 @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) } 245 get :record_invalid 218 246 end 219 247