简体   繁体   English

捕获错误并暂停程序的正确方法是什么?

[英]What is the proper way to catch an error and halt a program?

My intent is to break and return an error to the user upon a failed validation (using dry-validation). 我的目的是在验证失败(使用干燥验证)时打破并向用户返回错误。

Within a service object, I have: 在服务对象中,我具有:

def perform
  validate_coupon
  create_stripe_coupon
rescue ActiveRecord::RecordInvalid, ::Stripe::StripeError => exception
  puts "[STRIPE] Problem: #{exception.message}"
  OpenStruct.new(success?: false, coupon: coupon, error: exception.message)
else
  OpenStruct.new(success?: true, coupon: coupon)
end

def validate_coupon
  validate_coupon_object
rescue CouponError => exception
  puts "[CouponError] #{exception.message}"
  OpenStruct.new(success?: false, coupon: coupon, error: exception.message)
else
  OpenStruct.new(success?: true, coupon: coupon)
end

def create_stripe_coupon
  @coupon = ::Stripe::Coupon.create(
    :name => @coupon.name,
    :duration => @coupon.duration,
    :percent_off => @coupon.percent_off,
    :max_redemptions => @coupon.max_redemptions
    )
  save_coupon_object
end

I raise a custom error here in validate_coupon.rb: 我在validate_coupon.rb中提出一个自定义错误:

module PaymentServices
  module Stripe
    module Coupon
      module ValidateCoupon

        def schema
          Dry::Validation.Schema do
            required(:name) { str? }
            required(:duration) { str? }
            required(:percent_off) { gt?(0) & lt?(101) }
            required(:max_redemptions) { int? & gt?(0) }
          end
        end

        def validate_coupon_object
          result = schema.call(
            name: @coupon.name,
            duration: @coupon.duration,
            percent_off: @coupon.percent_off,
            max_redemptions: @coupon.max_redemptions
            )
          raise CouponError.new(result) if result.failure?
        end

      end
    end
  end
end

When the validation fails, the program throws the error but continues on and executes create_stripe_coupon . 验证失败时,程序将引发错误,但会继续并执行create_stripe_coupon

My desire is to break when the error is thrown within validate_coupon , thus stopping create_stripe_coupon from running. 我的愿望是在validate_coupon引发错误时中断,从而停止create_stripe_coupon的运行。

What is the best approach for this? 最好的方法是什么?

The problem is that the exception is rescued in validate_coupon method: 问题是该异常是在validate_coupon方法中挽救的:

def validate_coupon
  validate_coupon_object
rescue CouponError => exception
  puts "[CouponError] #{exception.message}"
  OpenStruct.new(success?: false, coupon: coupon, error: exception.message)
else
  OpenStruct.new(success?: true, coupon: coupon)
end

And the perform method knows nothing about the failure that happened in validate_coupon method: 而且perform方法对validate_coupon方法中发生的失败一无所知:

def perform
  validate_coupon
  create_stripe_coupon
rescue ActiveRecord::RecordInvalid, ::Stripe::StripeError => exception
  puts "[STRIPE] Problem: #{exception.message}"
  OpenStruct.new(success?: false, coupon: coupon, error: exception.message)
else
  OpenStruct.new(success?: true, coupon: coupon)
end

In order to fix it, you need something like: 为了修复它,您需要以下内容:

def perform
  result = validate_coupon
  create_stripe_coupon if result.success?
rescue ActiveRecord::RecordInvalid, ::Stripe::StripeError => exception
  puts "[STRIPE] Problem: #{exception.message}"
  OpenStruct.new(success?: false, coupon: coupon, error: exception.message)
else
  OpenStruct.new(success?: true, coupon: coupon)
end

Or 要么

def validate_coupon
  validate_coupon_object
rescue CouponError => exception
  puts "[CouponError] #{exception.message}"
  raise ActiveRecord::RecordInvalid
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM