从Rails

时间:2016-06-02 19:04:03

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

如何使用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并更新属性,使它们不属于范围。但这听起来像是一个无限循环。

有没有人有这个好的解决方案?

2 个答案:

答案 0 :(得分:2)

您可以在循环中放置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

答案 1 :(得分:0)

您可以使用retry。当从begin块调用时,它将重新执行整个rescue块。如果您只想重试有限次数,可以使用计数器。类似的东西:

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