Skip to content

Commit 044dad7

Browse files
ktimothydblock
authored andcommitted
Correctly choose exception handler in error middleware. Fixes #1364.
Now exception handler in options can be a symbol (or string) name of helper method to handle exception.
1 parent 59af167 commit 044dad7

File tree

5 files changed

+51
-10
lines changed

5 files changed

+51
-10
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44
* Your contribution here.
55

66
#### Features
7+
78
* [#1366](https://github.com/ruby-grape/grape/pull/1366): Store `message_key` on `Grape::Exceptions::Validation` - [@mkou](https://github.com/mkou).
89

10+
#### Fixes
11+
12+
* [#1365](https://github.com/ruby-grape/grape/pull/1365): Fix finding exception handler in error middleware - [@ktimothy](https://github.com/ktimothy).
13+
914
0.16.2 (4/12/2016)
1015
==================
1116

lib/grape/dsl/request_response.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ def represent(model_class, options)
157157

158158
def extract_with(options)
159159
return unless options.key?(:with)
160-
with_option = options[:with]
160+
with_option = options.delete(:with)
161161
return with_option if with_option.instance_of?(Proc)
162-
return if with_option.instance_of?(Symbol) || with_option.instance_of?(String)
162+
return with_option.to_sym if with_option.instance_of?(Symbol) || with_option.instance_of?(String)
163163
fail ArgumentError, "with: #{with_option.class}, expected Symbol, String or Proc"
164164
end
165165
end

lib/grape/middleware/error.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ def find_handler(klass)
4545
handler = options[:rescue_handlers].find(-> { [] }) { |error, _| klass <= error }[1]
4646
handler ||= options[:base_only_rescue_handlers][klass]
4747
handler ||= options[:all_rescue_handler]
48-
with_option = options[:rescue_options][:with]
49-
if with_option.instance_of?(Symbol)
50-
if respond_to?(with_option)
51-
handler ||= self.class.instance_method(with_option).bind(self)
48+
49+
if handler.instance_of?(Symbol)
50+
if respond_to?(handler)
51+
handler = self.class.instance_method(handler).bind(self)
5252
else
53-
fail NoMethodError, "undefined method `#{with_option}'"
53+
fail NoMethodError, "undefined method `#{handler}'"
5454
end
5555
end
56+
5657
handler
5758
end
5859

spec/grape/api_spec.rb

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,13 +1593,23 @@ class CommunicationError < StandardError; end
15931593
def rescue_arg_error
15941594
error!('500 ArgumentError', 500)
15951595
end
1596+
1597+
def rescue_no_method_error
1598+
error!('500 NoMethodError', 500)
1599+
end
15961600
end
15971601
subject.rescue_from ArgumentError, with: :rescue_arg_error
1598-
subject.get('/rescue_method') { fail ArgumentError }
1602+
subject.rescue_from NoMethodError, with: :rescue_no_method_error
1603+
subject.get('/rescue_arg_error') { fail ArgumentError }
1604+
subject.get('/rescue_no_method_error') { fail NoMethodError }
15991605

1600-
get '/rescue_method'
1606+
get '/rescue_arg_error'
16011607
expect(last_response.status).to eq(500)
16021608
expect(last_response.body).to eq('500 ArgumentError')
1609+
1610+
get '/rescue_no_method_error'
1611+
expect(last_response.status).to eq(500)
1612+
expect(last_response.body).to eq('500 NoMethodError')
16031613
end
16041614

16051615
it 'aborts if the specified method name does not exist' do
@@ -1608,6 +1618,31 @@ def rescue_arg_error
16081618

16091619
expect { get '/rescue_method' }.to raise_error(NoMethodError, 'undefined method `not_exist_method\'')
16101620
end
1621+
1622+
it 'correctly chooses exception handler if :all handler is specified' do
1623+
subject.helpers do
1624+
def rescue_arg_error
1625+
error!('500 ArgumentError', 500)
1626+
end
1627+
1628+
def rescue_all_errors
1629+
error!('500 AnotherError', 500)
1630+
end
1631+
end
1632+
1633+
subject.rescue_from ArgumentError, with: :rescue_arg_error
1634+
subject.rescue_from :all, with: :rescue_all_errors
1635+
subject.get('/argument_error') { fail ArgumentError }
1636+
subject.get('/another_error') { fail NoMethodError }
1637+
1638+
get '/argument_error'
1639+
expect(last_response.status).to eq(500)
1640+
expect(last_response.body).to eq('500 ArgumentError')
1641+
1642+
get '/another_error'
1643+
expect(last_response.status).to eq(500)
1644+
expect(last_response.body).to eq('500 AnotherError')
1645+
end
16111646
end
16121647

16131648
describe '.rescue_from klass, rescue_subclasses: boolean' do

spec/grape/dsl/request_response_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def self.imbue(key, value)
173173
it 'sets a rescue handler declared through :with option for each key in hash' do
174174
with_block = -> { 'hello' }
175175
expect(subject).to receive(:namespace_stackable).with(:rescue_handlers, StandardError => an_instance_of(Proc))
176-
expect(subject).to receive(:namespace_stackable).with(:rescue_options, with: with_block)
176+
expect(subject).to receive(:namespace_stackable).with(:rescue_options, {})
177177
subject.rescue_from StandardError, with: with_block
178178
end
179179
end

0 commit comments

Comments
 (0)