打破和 return 值的最佳方式

Best way to break and return a value

我有一个嵌套在其他几个方法中的方法,我希望此方法从所有递归方法中 break 并出现 returned 错误。例如,如果我在这里调用 pay_order

class API::StripeController < ApiController
  def my_api_action
    # ...
    order = create_order
    pay_order(order, token)
    # do things if payment is successful
  end
end

pay_order定义为:

def pay_order(order, token)
  begin
    order.pay(source: token)
  rescue Stripe::CardError => e
    break e
  end
end

如何突破所有父方法和return支付失败导致的卡错误?我需要 break and return ereturn e and break 之类的东西。但是我马上就知道 breakreturn 语句 return,所以我不能将它们链接起来(我不认为)。

我可以只向每个被调用的函数添加 return 语句,但我计划在很多地方使用这种方法,并且不打算永远需要它来表现不同,所以我寻找最可重用的编写方式。

你为什么rescuepay_order方法里面?我会在外圈救援。 鉴于以下内容:

def method_a
  10.times do |loop_a|
    method_b
  end
end

def method_b
  5.times do |loop_b|
    pay_order
  end
end

def pay_order
  ...
end

我会在method_a里面救援,例如:

def method_a
  10.times do |loop_a|
    method_b
  end
rescue Stripe::CardError => e
  # do whatever. no need to break
end

所有循环都是 "broken" 由引发异常自动产生的。

如果你想对pay_order方法中的异常做点什么,那我建议再rescue再raise:

def pay_order
  order.pay
rescue Stripe::CardError => e
  # do your stuff
  raise e
end

基本上可以用throw,或者raise(分别是fail,看讨论是用raise还是fail).

不同之处在于,使用 raise/fail,您会产生一个异常(使用 rescue 捕获),并且异常对象可以包含您想要 return.

使用 throw,您只是在调用链的上游执行某种 goto。着陆点使用 catch 定义(参见 here 示例)。这没有任何有效负载,这意味着您需要 "transport" 使用双方均可访问的对象(例如实例变量)返回任何数据。