Skip to content
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

Fixed finding handler in error middleware. Fixes #1364 #1365

Closed
wants to merge 1 commit into from

Conversation

ktimothy
Copy link
Contributor

No description provided.

@dblock
Copy link
Member

dblock commented Apr 19, 2016

Need CHANGELOG and a test, please.

@ktimothy
Copy link
Contributor Author

Sure, will do that tomorrow.

@ktimothy
Copy link
Contributor Author

Looks like the issue is a little bit deeper. Last call to rescue_from using with: overwrites previously set with: value.

For now option 'with:' is stored now in rescue_options in middleware/error, which makes it common for all exceptions.

I think the option 'with:' should be stored for each exception type separately.

@@ -157,9 +157,9 @@ def represent(model_class, options)

def extract_with(options)
return unless options.key?(:with)
with_option = options[:with]
with_option = options.delete(:with)
Copy link
Member

@dblock dblock Apr 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to dup options first, since you're modifying the original hash or continue just doing options[:with].

@dblock
Copy link
Member

dblock commented Apr 20, 2016

See minor-ish comments, otherwise good to merge?

@ktimothy
Copy link
Contributor Author

ktimothy commented Apr 20, 2016

Yes, just made small fixes.

@@ -104,7 +104,7 @@ def rescue_from(*args, &block)
handler = block
end

options = args.extract_options!
options = args.extract_options!.dup
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not what I meant. This particular one actually returns a new hash every time according to the documentation, so a dup is just doing extra unnecessary work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what's wrong with just checking options[:with] below? Why does it need to delete that value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular one actually returns a new hash every time

Oh, shame to me =)

Ok, we should have discussed it a little bit before I made my changes =). The option :with was used in middleware/error. I removed that usage, and stored its value in rescue_handlers hash.

So I decided to delete :with from options hash just to clean it from unused key. And that's why I had to fix request_response_spec.rb.

@dblock
Copy link
Member

dblock commented Apr 20, 2016

Sorry to be a pest, I have more questions ;)

@ktimothy
Copy link
Contributor Author

No problem ;)

@dblock
Copy link
Member

dblock commented Apr 21, 2016

@ktimothy I am so sorry to be thick and slow here (typing this from an island in the Caribbean). Amend the code to what you want it to be, and re-explain the whole thing to me like a two year old. Really appreciate your patience.

…ape#1364.

Now exception handler in options can be a symbol (or string) name of
helper method to handle exception.
@ktimothy
Copy link
Contributor Author

@dblock I hope you have a good time there =)

Ok, here is the whole thing.

At first I handled different exceptions using block syntax:

rescue_from ArgumentError do |e|
  rack_response({error: 'argument_error'}.to_json)
end

rescue_from :all do |e|
  rack_response({error: 'internal_error'}.to_json)
end

Then I wanted to move exception handlers from api class to helpers module. So I tried to use options :with:

rescue_from ArgumentError, with: :rescue_argument_error
rescue_from :all, with: :all_errors_handler

which made my api code much better.

But, unfortunately, grape stopped handling ArgumentError, calling :all_errors_handler instead. I started to dig into the problem, and found out, that :with is stored in :rescue_options hash, which is common for all exception types. Because of that :with option is overwritten every time you call rescue_from: ..., with: .... This behavior is definitely wrong, as we save last with: value in options.

As a solution I suggest to store with: in rescue_handlers and base_only_rescue_handlers, where block handlers are now stored. So values in these two hashes can be either a block or a symbol.

Error middleware now does not check rescue_options[:with], it tries to take handler from rescue_handlers`` andbase_only_rescue_handlers, then triesall_rescue_handler```. If handler is a symbol, we know that we should use helper method with corresponding name.

@dblock
Copy link
Member

dblock commented Apr 24, 2016

Merged via 044dad7, thanks for the clear explanation!

@dblock dblock closed this Apr 24, 2016
@ktimothy
Copy link
Contributor Author

Awesome, thanks!

@ktimothy ktimothy deleted the fix_find_error_handler branch May 19, 2017 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants