【问题标题】:Continue a loop after rescuing from an external API error in Rails从 Rails 中的外部 API 错误中救援后继续循环
【发布时间】:2016-06-02 19:04:02
【问题描述】:

如何使用rescue 继续循环。我举个例子

def self.execute
  Foo.some_scope.each do |foo|
    # This calls to an external API, and sometimes can raise an error if the account is not active
    App::Client::Sync.new(foo).start!
  end
end

所以通常rescue Bar::Web::Api::Error => e 会在方法结束时执行并且循环会停止。如果我可以更新被救出的foo 的属性并再次调用该方法,那么foo 将不会包含在范围内,我将能够再次启动循环。但问题是,我只想要每个foo 一次。所以这种方式将再次循环遍历所有现有的foo

还有什么方法可以做到这一点?我可以创建一个在execute 方法顶部调用的私有方法。这可以循环遍历foo 并更新属性,因此它们不属于范围。但这听起来像是一个无限循环。

有人有好的解决办法吗?

【问题讨论】:

  • 不是 ruby​​ 专家,但我认为您可以看看 this 在循环中以非中断方式使用它(最坏的情况是空重试)

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

您可以在循环中放置 beginrescue 块。您谈论“更新 foo 的属性”,但似乎您只想确保在重新启动循环时不会处理此 foo,但您不需要重新启动循环。

def self.execute
  Foo.some_scope.each do |foo|
    # This calls to an external API, and sometimes can raise an error if the account is not active
    begin
      App::Client::Sync.new(foo).start!
    rescue Bar::Web::Api::Error
      foo.update(attribute: :new_value) # if you still need this
    end
  end
end

【讨论】:

  • 谢谢,我喜欢这个解决方案比使用retry
【解决方案2】:

您可以使用retry。当从 rescue 块调用时,它将重新执行整个 begin 块。如果您只希望它重试有限次数,您可以使用计数器。比如:

def self.execute
  Foo.some_scope.each do |foo|
    num_tries = 0
    begin
      App::Client::Sync.new(foo).start!
    rescue
      num_tries += 1
      retry if num_tries > 1
    end
  end
end

文档here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    相关资源
    最近更新 更多