Issue #10481 has been updated by Alex Boyd.


Brian Hempel wrote:
> Sometimes code libraries forget to make a separate object for every error

This was, in fact, one of the reasons that motivated me to propose this in the first place - I've been doing some work with a web service whose documentation is less than thorough about all of the various error codes it can issue when it fails, and that makes having a separate exception for each and every error in a client library for said web service difficult.

bruka <bruka / idatainc.com> wrote:
> I'm trying to think of use cases for this

In addition to the above, here's another one: a block of code that could fail for reasons beyond your control, where you want to catch errors in a production environment and handle them as gracefully as possible while allowing them to pass through in development and test. In Rails, this could look like:

~~~
begin
  ...critical code here...
rescue SomeError if Rails.env.production?
  ...try to recover as best we can...
end
~~~

This was also a motivating reason for my proposing this.

> You read the entire loop and at the end you realize that it only runs in certain cases. Similar with the conditional rescues. You're jumping back and forth in your method to try to figure out what happens when. Not fun.
I agree that jumping back and forth can be confusing, but I would argue that this is no worse than `rescue` clauses as they currently are, and even *better* when the alternative is to have a `raise unless` inside the rescue body where it could be missed.

> Moreover, as another person noted, skipping the rescue clause can deprive you of valuable debugging information. Why not just send the error to another object to be processed:
That seems like a separate issue entirely - insofar as there's already a way to limit the scope of what's being rescued (re-`raise`ing and only rescuing certain exception types in the first place), rescue conditionals won't make this any different. I would also argue that having a separate class or method to encapsulate what would otherwise be a line or two of logic is overkill, and just serves to obfuscate what's really going on further.

I do agree that (like most language features) there's a potential for abuse here, but (in my opinion) the benefits outweigh said potential. That's my 3 cents. :-)

----------------------------------------
Feature #10481: Add "if" and "unless" clauses to rescue statements
https://bugs.ruby-lang.org/issues/10481#change-50303

* Author: Alex Boyd
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category: 
* Target version: 
----------------------------------------
I'd like to propose a syntax change: allow boolean "if" and "unless" clauses to follow a rescue statement.

Consider the following:

~~~ruby
begin
  ...
rescue SomeError => e
  if e.error_code == 1
    ...handle error...
  else
    raise
  end
end
~~~

This is a fairly common way of dealing with exceptions where some condition above and beyond the exception's type determines whether the exception should be rescued. It's verbose, though, and it's not obvious at first glance exactly what conditions are being rescued, especially if "...handle error..." is more than a few lines long. I propose that the following be allowed:

~~~ruby
begin
  ...
rescue SomeError => e if e.error_code == 1
  ...handle error...
end
~~~

"unless" would, of course, be allowed as well:

~~~ruby
begin
  ...
rescue SomeError => e unless e.error_code == 2
  ...handle error...
end
~~~

A rescue statement whose boolean condition failed would be treated the same as if the exception being raised didn't match the exception being rescued, and move on to the next rescue statement:

~~~ruby
begin
  ...
rescue SomeError => e if e.error_code == 1
  ...handle error code 1...
rescue SomeError => e if e.error_code == 2
  ...handle error code 2...
end
~~~

And finally, catch-all rescue statements would be allowed as well:

~~~ruby
begin
  ...
rescue => e if e.message == "some error"
  ...handle error...
end
~~~


---Files--------------------------------
rescue-conditions.diff (6.76 KB)
rescue-conditions.diff (6.57 KB)
smime.p7s (4.78 KB)


-- 
https://bugs.ruby-lang.org/