-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exceptions aren't rescued in a predictable order #1405
Exceptions aren't rescued in a predictable order #1405
Conversation
I feel like rescuing errors should follow the rule of least surprise, which is that they should be rescued in order of their declaration until one matches, so |
It's look like that there is a little misunderstanding. That new spec fails, and it means that code acts like you expect it to act: the first who matches, wins. |
Frankly speaking, I'm quite frustrated after looking on how nested
The last two ones fail, but I was sure they should be green. |
There's ordering of rescues and there's mounting of other APIs. I'll maintain that what we always want is to rescue in order. That's partly because route/api matching works like this, imagine if a more specific route was matched first, it would make things very hard to predict and lots of side effects. Why is the above a problem? Why can't one order rescues the way you want them to match? Why is that frustrating? |
You know, I thought they are something like overriding a method in a class descendants: if both parent and child have a method :do_smth, child's one takes a priority. But I see your point now, thanks for clarifying. |
Not sure. I cannot find that spec - want to copy the relevant code out here or give a link? |
Here is the link. Or you could just paste this code to it 'prefers rescues defined by mounted if they rescue similar error class' do
subject.rescue_from StandardError do
rack_response("outer rescue")
end
app = Class.new(Grape::API)
subject.namespace :mounted do
rescue_from StandardError do
rack_response("inner rescue")
end
app.get('/fail') { raise 'doh!' }
mount app
end
get '/mounted/fail'
expect(last_response.body).to eq('inner rescue')
end If I understand you correctly, it should fail (returning 'outer rescue'). But it's green. |
Not here because of I guess the metaphor of a list isn't really what we have here. We have a tree. Routes evaluate sequentially going down the tree by doing a depth-first-search, exceptions bubble up the other way around, exactly like any recursive program. |
But then these specs should be green, too. They also use it 'prefers rescues defined by mounted even if outer is more specific' do
subject.rescue_from ArgumentError do
rack_response("outer rescue")
end
app = Class.new(Grape::API)
subject.namespace :mounted do
rescue_from StandardError do
rack_response("inner rescue")
end
app.get('/fail') { raise ArgumentError.new }
mount app
end
get '/mounted/fail'
expect(last_response.body).to eq('inner rescue')
end
it 'prefers more specific rescues defined by mounted' do
subject.rescue_from StandardError do
rack_response("outer rescue")
end
app = Class.new(Grape::API)
subject.namespace :mounted do
rescue_from ArgumentError do
rack_response("inner rescue")
end
app.get('/fail') { raise ArgumentError.new }
mount app
end
get '/mounted/fail'
expect(last_response.body).to eq('inner rescue')
end That's why I was frustrated: in different situations different priority is observed. |
I agree, both should succeed here. Can you fix the rubocop stuff in this PR please so we can all see the spec failures? |
I've updated the branch. These specs fails:
|
I think the issue appears because here we use |
I think you have it exactly right @hedgesky. Marking this as confirmed bug. |
I've added a new class called |
This PR is great, well done @hedgesky, lets get this merged. Can you please add a line to CHANGELOG and write a paragraph in UPGRADING for the scenarios that will break? Probably want some more README updates too. Squash your commits, too. If a method is unused it can be deleted ;) |
Not that simple: there are Regarding changelog, readme and upgrading — will do that soon. |
Rescue_from clauses defined in namespaces would take a priority over ones defined in the root scope
Is everything OK with it? |
Yep, Github doesn't send a notification on a push. Thank you, merging! |
I'm starting to work on errors handling improvements. First of all, I've introduced a failing spec: from my point of view, rescuing specific error should take precedence over rescuing its base, but it doesn't.
@dblock, could you please explain to me, if it's a bug or a feature? Should I keep this behavior during my changes?