关于Ruby:Ruby – 即使引发了Stripe异常WAS,else块中的代码也会执行

Ruby - code in else block executes even though Stripe exception WAS thrown

我的代码的简化版本:

1
2
3
4
5
6
7
8
9
10
11
1.upto(2) do |try|
  begin
    puts"Start"
  rescue => e
    if try == 2
      puts"Error - #{e}"
    end
  else
    puts"Success"
  end
end

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

1
2
3
4
Start
Start
Error - some message
Success

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

更新

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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的答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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


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

我已修改您的代码以引发异常,以便我们可以测试它:

1
2
3
4
5
6
7
8
9
10
11
12
1.upto(2) do |try|  
  begin
    puts"Start"
    raise 'xxxx'
  rescue => e
    if try == 2
      puts"Error - #{e}"
    end
  else
    puts"Success"
  end
end

这是输出:

1
2
3
Start
Start
Error - xxxx

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

else块用于块完成时没有抛出异常。 另一种是ensure,无论块是否成功完成,无论如何都会执行。

更新

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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

看看是否能解决你的问题。