Ruby - 即使抛出了 Stripe 异常,else 块中的代码也会执行
Posted
技术标签:
【中文标题】Ruby - 即使抛出了 Stripe 异常,else 块中的代码也会执行【英文标题】:Ruby - code in else block executes even though Stripe exception WAS thrown 【发布时间】:2015-11-02 21:59:03 【问题描述】:我的代码的简化版:
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
换句话说,StripeErrorEmail
和 RoadrunnerEmailAlert
都在开火
更新 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
【问题讨论】:
你有没有看到错误信息?我在本地尝试过,救援块永远不会执行,因为,没有例外。我建议你看看this post,它对 Ruby begin-rescue 流程有很好的解释。 您希望发生什么? 【参考方案1】:不,如果出现异常,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
看看能不能解决你的问题。
【讨论】:
是的......这正是应该发生的......但我认为我通过输入简化代码对自己造成了伤害......因为使用你的例子,我也得到了那个结果,但它在我的实际代码中不起作用,我将对其进行修改 @james 查看我编辑的代码,看看是否适合您。如果else
块仍在执行,则意味着由于某种原因未正确捕获异常。我们需要弄清楚这一点!告诉我!
嘿,首先非常感谢您的详细回答。我已经尝试过了,它仍然没有被正确捕获。我也在 Stripe 上尝试过不同的错误。不管出现什么错误,什么情况,else
仍然会被执行
您能否完全按照问题部分中的方式分享您的最新代码?另外,您可以打印条带 API 生成的错误吗?打印这些信息: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]"
并更新您的问题。
好的,我回家再看看。以上是关于Ruby - 即使抛出了 Stripe 异常,else 块中的代码也会执行的主要内容,如果未能解决你的问题,请参考以下文章