Permalink
Browse files

allowing a sequence of error blocks with the same http status code to…

… be chained
  • Loading branch information...
1 parent 1399a7b commit 4f0e1d4ef37158c85ac38b64d8930af172ce1be0 @snaggled snaggled committed Apr 26, 2012
Showing with 46 additions and 5 deletions.
  1. +9 −5 lib/sinatra/base.rb
  2. +37 −0 test/mapped_error_test.rb
View
@@ -989,9 +989,13 @@ def handle_exception!(boom)
def error_block!(key, *block_params)
base = settings
while base.respond_to?(:errors)
- next base = base.superclass unless args = base.errors[key]
- args += [block_params]
- return process_route(*args)
+ next base = base.superclass unless args_array = base.errors[key]
+ args_array.reverse_each do |args|
+ first = args == args_array.first
+ args += [block_params]
+ resp = process_route(*args)
+ return resp unless resp.nil? && !first
+ end
end
return false unless key.respond_to? :superclass and key.superclass < Exception
error_block!(key.superclass, *block_params)
@@ -1091,11 +1095,11 @@ def disable(*opts)
# Define a custom error handler. Optionally takes either an Exception
# class, or an HTTP status code to specify which errors should be
# handled.
- def error(*codes, &block)
+ def error(*codes, &block)
args = compile! "ERROR", //, block
codes = codes.map { |c| Array(c) }.flatten
codes << Exception if codes.empty?
- codes.each { |c| @errors[c] = args }
+ codes.each { |c| (@errors[c] ||= []) << args }
end
# Sugar for `error(404) { ... }`
View
@@ -14,6 +14,8 @@ class FooStatusOutOfRangeError < RuntimeError
def code; 4000 end
end
+class FirstError < RuntimeError; end
+class SecondError < RuntimeError; end
class MappedErrorTest < Test::Unit::TestCase
def test_default
@@ -207,6 +209,41 @@ def test_default
assert_equal 500, status
end
+ it "allows a stack of exception_handlers" do
+ mock_app {
+ set :raise_errors, false
+ error(FirstError) { 'First!' }
+ error(SecondError) { 'Second!' }
+ get('/'){ raise SecondError }
+ }
+ get '/'
+ assert_equal 500, status
+ assert_equal 'Second!', body
+ end
+
+ it "allows an exception handler to pass control to the next exception handler" do
+ mock_app {
+ set :raise_errors, false
+ error(500, FirstError) { 'First!' }
+ error(500, SecondError) { pass }
+ get('/') { raise 500 }
+ }
+ get '/'
+ assert_equal 500, status
+ assert_equal 'First!', body
+ end
+
+ it "allows an exception handler to handle the exception" do
+ mock_app {
+ set :raise_errors, false
+ error(500, FirstError) { 'First!' }
+ error(500, SecondError) { 'Second!' }
+ get('/') { raise 500 }
+ }
+ get '/'
+ assert_equal 500, status
+ assert_equal 'Second!', body
+ end
end
describe 'Custom Error Pages' do

0 comments on commit 4f0e1d4

Please sign in to comment.