Ruby - 即使引发了Stripe异常WAS {else},也会执行else块中的代码

时间:2015-08-10 20:47:27

标签: ruby-on-rails ruby exception-handling stripe-payments rescue

我的代码的简化版本:

1.upto(2) do |try|
  begin
    puts "Start"
  rescue => e
    if try == 2
      puts "Error - #{e}"
    end
  else
    puts "Success"
  end
end

我的问题是,当我遇到错误时,会发生这种情况:

Start
Start
Error - some message
Success

真的在这里摸不着头脑,因为这不应该发生什么......有什么想法吗?

更新

好吧,我认为通过添加代码的简化版本,我自己也是一种伤害,因为它可行,但下面的完整版本没有。即,当Stripe抛出API异常时,电子邮件仍在触发。

1.upto(2) do |try|
  Stripe.api_key = ENV['Stripe_Secret_Key']
  begin
    customer = Stripe::Customer.create(
      :source => params[:stripeToken],
      :email => @rentalrequest.email
    )
    @charge = Stripe::Charge.create(
      amount: (@rentalrequest.actual_amount * 100), # Stripe requires cents
      currency: "usd",
      customer: customer.id,
      description: "Payment from #{@rentalrequest.email} for gear rental"
    )
  rescue => e
    if try == 2
      logger.fatal "Stripe error: #{e.class}, #{e.message}"
      StripeErrorEmail.new.async.perform(e.class, e.message, @rentalrequest.id)
      render "rental_requests/new" and return
    end
  else
    RoadrunnerEmailAlert.new.async.perform(@rentalrequest.id)
  end
end

换句话说,StripeErrorEmailRoadrunnerEmailAlert都在解雇

更新KM的答案

def error_handle(e, id)
  # Since it's a decline, Stripe::CardError will be caught
  body = e.json_body
  err  = body[:error]

  puts "Status is: #{e.http_status}"
  # => 400
  puts "Type is: #{err[:type]}"
  # => invalid_request_error
  puts "Code is: #{err[:code]}"
  # => nil
  puts "Param is: #{err[:param]}"
  # => nil
  puts "Message is: #{err[:message]}"
  # => You cannot use a Stripe token more than once

  logger.fatal "Stripe error: #{e.class}, #{e.message}"
  StripeErrorEmail.new.async.perform(e.class, e.message, id)
  render "rental_requests/new" and return
end

def charge
  @rentalrequest = RentalRequest.find(params[:rentalrequest_id])

  # Up to two tries
  1.upto(2) do |try|
    Stripe.api_key = ENV['Stripe_Secret_Key']
    begin
      customer = Stripe::Customer.create(
        :source => params[:stripeToken],
        :email => @rentalrequest.email
      )
      @charge = Stripe::Charge.create(
        amount: (@rentalrequest.actual_amount * 100), # Stripe requires cents
        currency: "usd",
        customer: customer.id,
        description: "Payment from #{@rentalrequest.email} for gear rental"
      )
    rescue Stripe::CardError => e
      if try == 2
        error_handle(e, @rentalrequest.id)
      end
    rescue Stripe::InvalidRequestError => e
      if try == 2
        error_handle(e, @rentalrequest.id)
      end
    rescue Stripe::AuthenticationError => e
      if try == 2
        error_handle(e, @rentalrequest.id)
      end
    rescue Stripe::APIConnectionError => e
      if try == 2
        error_handle(e, @rentalrequest.id)
      end
    rescue Stripe::StripeError => e
      if try == 2
        error_handle(e, @rentalrequest.id)
      end
    rescue => e
      if try == 2
        error_handle(e, @rentalrequest.id)
      end  
    else
      RoadrunnerEmailAlert.new.async.perform
    end
  end
end

1 个答案:

答案 0 :(得分:2)

不,如果有异常,则不会执行else块。

我修改了您的代码以引发异常,以便我们可以对其进行测试:

1.upto(2) do |try|  
  begin
    puts "Start"
    raise 'xxxx'
  rescue => e
    if try == 2
      puts "Error - #{e}"
    end
  else
    puts "Success"
  end
end

这是输出:

Start
Start
Error - xxxx

清楚地表明,当存在异常时,else块不会被执行。

else块用于块在没有抛出异常的情况下完成。另一种是ensure,无论块是否成功完成,都会执行。

更新

查看您的最新代码,看起来像条纹问题。尝试更优雅地处理条带错误,如下所示:

begin
  customer = Stripe::Customer.create(
  :source => params[:stripeToken],
  :email => @rentalrequest.email
)

@charge = Stripe::Charge.create(
  amount: (@rentalrequest.actual_amount * 100), # Stripe requires cents
  currency: "usd",
  customer: customer.id,
  description: "Payment from #{@rentalrequest.email} for gear rental"
)
rescue Stripe::CardError => e
  # Since it's a decline, Stripe::CardError will be caught
  body = e.json_body
  err  = body[:error]

  puts "Status is: #{e.http_status}"
  puts "Type is: #{err[:type]}"
  puts "Code is: #{err[:code]}"
  # param is '' in this case
  puts "Param is: #{err[:param]}"
  puts "Message is: #{err[:message]}"
rescue Stripe::InvalidRequestError => e
  # Invalid parameters were supplied to Stripe's API
rescue Stripe::AuthenticationError => e
  # Authentication with Stripe's API failed
  # (maybe you changed API keys recently)
rescue Stripe::APIConnectionError => e
  # Network communication with Stripe failed
rescue Stripe::StripeError => e
  # Display a very generic error to the user, and maybe send
  # yourself an email
rescue => e
  # Something else happened, completely unrelated to Stripe
end

并查看是否能解决您的问题。