Рубиновый спасательный блок или класс - PullRequest
0 голосов
/ 04 февраля 2012

Кажется, я снова использую те же rescue с. Было бы возможно иметь блок rescue? Так что вместо:

while count != 0 do 
<<code>>
rescue error1
<<code>>
retry
rescue error2
<<code>>
break
end

Я могу иметь:

def rescue_block
rescue error 1
<<code>>
retry
rescue error 2
<<code>>
break
end

while count !=0
<<code>>
rescue_block
end

Обратите внимание на break и retry. Действия rescue_block должны применяться к циклу, а не к самому себе.

EDIT:

Используя гем Twitter, большинство ошибок Twitter можно обрабатывать аналогичным образом (т. Е. Если вы превысили лимит API, подождите.). Полный код:

while cursor != 0 do
  begin
    grabFollowers ? f = Twitter.follower_ids(username,{:cursor=>cursor}) : f = Twitter.friend_ids(username,{:cursor=>cursor})
    outfile.puts(f.ids) if writeHumanReadable
    arrayOfIds << f.ids
    cursor = f.next_cursor
  rescue Twitter::Error::Unauthorized
    break
  rescue Twitter::Error::BadRequest
    #ran out of OAUTH calls, waits until OAUTH reset + 10 seconds.
    outErrorFile = File.new("#{username.to_s}-ERROR.txt",'w')
    resetTime = Twitter.rate_limit_status.reset_time_in_seconds
    current = Time.now.to_i
    pauseDuration = resetTime-current+10
    outErrorFile.puts(Time.now)
    outErrorFile.puts(pauseDuration/60)
    outErrorFile.close
    sleep(pauseDuration)
    retry
  rescue Twitter::Error::NotFound
    break
  rescue Twitter::Error::ServiceUnavailable
    sleep(60*5)
    retry
  end
  sleep(2)
end

1 Ответ

3 голосов
/ 04 февраля 2012

Ваш пример показывает, что вам нужны макросы, которых у Ruby нет.

Мы можем довольно близко подойти к вашему примеру с блоками, но действительно трудно ответить на этот вопрос, не зная вашего варианта использования. (Я полагаю, что вы не используете исключения для управления потоком данных, это обычно вызывает недовольство, поскольку управление потоком данных не является исключительной ситуацией).

В зависимости от того, что вы пытаетесь сделать, бросок и ловля могут лучше соответствовать вашим потребностям, чем исключения.

class Example
  RetryException = Class.new StandardError
  BreakException = Class.new StandardError

  attr_accessor :count

  def initialize
    self.count = 10
  end

  def rescue_block
    yield
  rescue RetryException
    self.count -= 1
    retry
  rescue BreakException
    self.count -= 2
    return
  end

  def count_down
    rescue_block { yield count while 0 < count }
  end
end

Example.new.count_down do |count|
  count # => 10, 9, 8, 7, 6, 5
  raise Example::BreakException if count == 5
  raise Example::RetryException
end

Example.new.count_down do |count|
  count # => 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
  raise Example::RetryException
end
...