From: "svoop (Sven Schwyn)" Date: 2021-09-02T22:18:12+00:00 Subject: [ruby-core:105125] [Ruby master Feature#18145] Rescue by nested exception Issue #18145 has been reported by svoop (Sven Schwyn). ---------------------------------------- Feature #18145: Rescue by nested exception https://bugs.ruby-lang.org/issues/18145 * Author: svoop (Sven Schwyn) * Status: Open * Priority: Normal ---------------------------------------- The introduction of `Exception#cause` helps a lot when debugging nested errors. Same goes for wrapped errors. I'm not really sure whether such wrapped errors are an advisable pattern to begin with, feel free to comment on this, but I've used it in a couple of vendored gems dealing with payment providers. Here's some simplified code to illustrate. The `Payment` class deals with all the gory things such as authorization, coercion or API quirks. A simplified version might look like this: ```ruby require 'rest_client' module Provider class FindError < StandardError; end class Payment attr_reader :id, :amount private_class_method :new def initialize(id, amount) @id, @amount = id, amount end def self.find(id) response = RestClient.get('https://api.provider.com/payments', params: { id: id }) body = JSON.parse(response.body) new(id, body.fetch('amount')) rescue raise FindError end end end ``` You can easily `rescue` from anything going wrong when loading a payment: ```ruby begin Provider::Payment.find(123) rescue FindError ... end ``` However, you might want to rescue differently for some specific causes (e.g. not found) but not for others (e.g. timeout): ```ruby begin Provider::Payment.find(123) rescue FindError => error if error.cause.instance_of? RestClient::NotFound ... else ... end end ``` How about allowing to rescue by nested exception with a syntax like? ```ruby begin Provider::Payment.find(123) rescue FindError & RestClient::NotFound ... rescue FindError ... end ``` -- https://bugs.ruby-lang.org/ Unsubscribe: