In Ruby, I want to do something special for a specific exception but not enough to have a specific rescue. What is the proper syntax to check for a specific exception within rescue?
Sample (non-working) code:
begin
c = d
rescue => ex
if ex == NameError
puts 'NameError'
else
puts ex.message
end
end
The code between “begin” and “rescue” is where a probable exception might occur. If an exception occurs, the rescue block will execute. You should try to be specific about what exception you're rescuing because it's considered a bad practice to capture all exceptions.
In Ruby, we use the rescue keyword for that. When rescuing an exception in Ruby, you can specify a specific error class that should be rescued from. Note: When using raise without specifying an exception class, Ruby will default to RuntimeError .
Ruby Internal try catch (raise and rescue) In case exceptions happen in the begin block it will halt and control will go between rescue and end, and we can return a valid message for the user in case of exceptions. Every time for a rescue statement Ruby checks and compares the exception raised for each parameter.
For each rescue clause, the raised Ruby exception is compared against each parameter and the match succeeds if the exception in the clause is the same as or a superclass of the thrown exception. If the thrown Ruby exception does not match any of the specified exception types, the else block gets executed.
In your example ex
is an instance of on exception, and will not give expected results when comparing to the class itself with the ==
operator, which is a Class
object. You need to check the error's class against the actual class object.
# A NameError or an error that is a subclass of NameError
ex.is_a?(NameError)
ex.kind_of?(NameError)
# NameError ONLY, not even sub-classes of NameError
ex.instance_of?(NameError)
There are numerous other ways you could check, though the previous methods I outlined are the most commonly used, and typically "preferred" way. Although equality could still be used on the classes, it is typically not the suggested way to achieve it, as it is less flexible, and less clear on the underlying intention, where the above examples indicate exactly how you would like to handle subclasses of the specified error.
ex.class == NameError
I found this answer that explains the subtle differences pretty well.
I would go with multiple rescue blocks - one that only catches NameError
and another that catches all error classes:
begin
c = d
rescue NameError => ex
puts 'NameError'
rescue => ex
puts ex.message
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With