【问题标题】:Best way to break and return a value打破和返回值的最佳方法
【发布时间】:2018-07-05 06:20:57
【问题描述】:

我有一个嵌套在其他几个方法中的方法,我希望这个方法从所有递归方法中break 返回错误。例如,如果我在这里调用了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

如何突破所有父方法并返回支付失败导致的卡错误?我需要break and return ereturn e and break 之类的东西。但我知道breakreturn 语句都会立即返回,所以我不能链接它们(我不认为)。

我可以在每个被调用的函数中添加 return 语句,但我计划在很多地方使用这种方法,并且不打算让它表现得不同,所以我正在寻找最可重复使用的编写方式。

【问题讨论】:

  • 为什么不挽救顶层的错误my_api_action

标签: ruby-on-rails ruby return break


【解决方案1】:

你为什么在pay_order 方法中使用rescue?我会在外环上进行救援。 鉴于以下情况:

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

通过引发异常,所有循环都会自动“中断”。

如果你想对 pay_order 方法中的异常做一些事情,那么我建议你再次救援和提高:

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

【讨论】:

  • “你为什么要在 pay_order 方法中进行救援?” - @coorasse 我认为在支付方法本身中处理与付款相关的异常是个好主意。方法pay_order 可以在应用程序的任何地方使用。
  • 我想我是这样写的,因为我对错误处理有基本的了解。我想找到一种方法,只在 pay_order 方法中编写一次救援语句,也许想得太难了。
  • 如果你想在支付方式中本地化支付错误救援,你可以定义自己的异常来包装支付错误,但机制保持不变。
  • 那么我回答的第二部分是给你的。救援,做你的事情并再次加注以打破循环。
【解决方案2】:

基本上,您可以使用throwraise(分别为fail,有关是否使用raisefail 的讨论,请参阅here)。

不同之处在于,使用 raise/fail,您会产生一个异常(您可以使用 rescue 捕获该异常),并且 Exception 对象可以包含您想要返回的数据作为有效负载。

使用throw,您只是在调用链向上执行一种goto。使用catch 定义着陆点(参见例如here)。这没有任何有效负载,这意味着您需要使用双方都可访问的对象(例如实例变量)“传输”任何数据。

【讨论】:

  • 好答案。要记住的一件事是,与许多其他语言相比,在 Ruby 中生成异常是一项昂贵的操作,因为这里提到的“有效负载”是 Ruby 必须生成整个调用堆栈并返回它。这就是为什么 rescue next 在循环中通常不受欢迎的原因(以及其他原因......)。所以实际上归结为您是否需要异常数据。如果您不关心异常,那么throw .. catch 似乎是要走的路。此外,一个简单的return 会跳出嵌套循环,但并非总是可以做到。
猜你喜欢
  • 2019-05-10
  • 2013-08-16
  • 2020-09-03
  • 1970-01-01
  • 2013-06-11
  • 2012-02-26
  • 1970-01-01
  • 2022-08-02
  • 2012-01-30
相关资源
最近更新 更多