-
-
Notifications
You must be signed in to change notification settings - Fork 115
Add custom exception handlers #44
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
Conversation
@krzyzak Thanks for this PR. My idea for feature is to give more power to developers to handle exceptions with an alternative logic from What I'd really want achieve is a command-query separation and make the handler a void method. def _handle_exception(exception)
raise unless configuration.handle_exceptions
handler = configuration.handled_exceptions[exception.class]
code = if handler.respond_to?(:to_proc)
handler.to_proc.call(self, exception)
else
configuration.exception_code(exception.class)
end
halt code
end and then.. def halt(code = nil)
status(*Http::Status.for_code(code)) unless code.nil?
throw :halt
end and having a custom handler like: def handle_my_exception(exception)
self.status = 501
self.body = 'Please go away!'
end
# ...or
def handle_my_exception(exception)
status 501, 'Please go away!'
end
# ...or
def handle_my_exception(exception)
abort "Can't manage this exception: #{ e.message }"
end What do you think? |
I love this approach! How about change in |
@jodosha I started playing aroud with that code, and I found that it would be impossible to use procs at the moment (because |
@krzyzak I was doing the same and going to suggest the same thing: only accept integers or symbols for direct status code assigment or custom exception handling via concrete method. Also, we should use |
- Allow only method name or status code as handler - Don't require to return array with code and body
@krzyzak I like the idea of the exceptions hierarchy, but we should rethink a little bit the implementation: def _handle_exception(exception)
raise unless configuration.handle_exceptions
handler = configuration.handled_exceptions[exception.class] # 1
code = if handler.respond_to?(:to_proc)
handler.to_proc.call(self, exception)
else
configuration.exception_code(exception.class) # 2
end
halt code
end Lines # throwable.rb
def _handle_exception(exception)
raise unless configuration.handle_exceptions
halt(
method(
configuration.exception_handler(exception)
).call(exception)
)
end
def default_exception_handler(exception)
# override me!
end # configuration.rb
# deprecate exception_code and add the following method:
def exception_handler(exception)
# Here we can also implement the concept of hierarchy with @krzyzak `is_a?` suggestion
handled_exceptions.fetch(exception.class) { :default_exception_handler }
end This is just a spike, and I don't know if it can work, but it reflects better the new concept of exception handler and avoids conditional statements. What do you think? |
- Remove `exception_code` in favour of `exception_handler` in Configuration - Add Thorwable::Handlers, which defines handlers for all status codes - Remove ability to specify handlers by status code in favour of explicit handlers
@jodosha I played around with that new approach, and (mostly) it works. Because of that, I removed ability to specify exception handling with explicit status code (eg. I know that changes behaviour of |
@jodosha As a recap, I’ll write short summarisation of our conversation on chat. It’s just not worth to introduce so many new methods to solve so simple problem (and it might cause confusion, if someone would like to implement method like There was also one issue that I've been using protected If you like current changes, then the only thing left is to update documentation. |
With this code, you can handle your exceptions with custom logic (method or anything callable) – the only constraint is that it must return an array with status code and message.
This is still work in progress, just wanted to show my approach and current progress. I’ll update docs once everything else will be settled.
I’m still in doubt if if wouldn’t be more convinient to change one more function:
configuration.excepton_code
. At the moment it checks a hash for a key with exact match, which isn’t very flexible for me. I’d love to have something like this in my controller:To achieve this, I’d have to specify all possible exception classes, which of course is not an option.
Thus, I’d suggest doing something like this:
What do you thing about such approach?