我使用stripe作为支付处理器。
在应用程序中,我向Stripe发送执行费用或其他类型进程的请求,并且基本上使用与下面相同的错误处理样板。
rescue Stripe::InvalidRequestError => e,
# do something
rescue Stripe::AuthenticationError => e,
# do something
rescue Stripe::APIConnectionError => e,
# do something
rescue Stripe::StripeError => e
# do something
rescue => e
# do something
end
虽然我在每个API调用中肯定rescue
这些错误类型,这是很多样板代码,但我只想在所有这些错误类型上rescue
,然后构建一个方法做日志记录,发送通知等事情。
如何以更干净的方式将这些捆绑到一个异常处理程序中(如下所示)?
def call
plan = Plan.new(attrs)
return plan unless plan.valid?
begin
external_card_plan_service.create(api_attrs)
rescue Exceptions::Stripe => e
plan.errors[:base] << e.message
return plan
end
plan.save
plan.update(is_active: true, activated_at: Time.now.utc)
plan
end
答案 0 :(得分:4)
在您的应用中的某个位置定义一个变量/常量/方法,它返回您要营救的错误列表。例如:
STRIPE_ERRORS = [Stripe::InvalidRequestError, String::AuthenticationError]
在救援区中,您可以使用splat操作员来解救其中任何一个:
begin
<raise errors>
rescue *STRIPE_ERRORS => e
<handle errors>
end
您可以查看使用e.class
答案 1 :(得分:4)
不完全确定do something
是否与每种情况相同。如果没有,这可能会做你想要的:
def handle_stripe_errors
yield
rescue Stripe::AuthenticationError => e,
# do something
rescue Stripe::APIConnectionError => e,
# do something
rescue Stripe::StripeError => e
# do something
rescue => e
# do something
end
handle_stripe_errors do
external_card_plan_service.create(api_attrs)
end
答案 2 :(得分:1)
这是与Max和Amadan的解决方案相结合的另一种解决方案,它使DRY的功能更多一些,并成为可重用的类。
该解决方案利用了Rails around_action
,您可以在其中围绕其方法定义控制器中的动作。
即
...
STRIPE_ERRORS = [Stripe::InvalidRequestError, String::AuthenticationError, ...]
around_action :stripe_error_handler
...
def stripe_error_handler
yield
rescue *STRIPE_ERRORS => e
<handle errors>
end
...
**您可以指定around_action
适用于哪些方法!
要使其更具可重用性,您可以定义一个包含常量STRIPE_ERRORS的类,并在救援部分(StripeErrorHander.new(e)
中用e初始化,这样您可以指定每个Stripe错误的行为(也许发送一个电子邮件/闲置邮件中出现的特定错误,请使该错误邮件更具可读性)。
对类的简化外观可能是这样的:
class StripeErrorHandler
STRIPE_ERRORS = [
Stripe::CardError,
Stripe::RateLimitError,
...
].freeze
def initialize(error)
@error = error
end
def message
@error.message
end
def status
case @error
when Stripe::CardError
:unprocessable_entity
when Stripe::RateLimitError
:service_unavailable
else
:internal_server_error
end
end
end