Mr. Demetrius Michael
Mr. Demetrius Michael

Reputation: 2406

Ruby rescue block or class

I seem to be reusing the same rescues. Would it be possible to have a rescue block? So instead of:

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

I can have:

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

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

Notice the break and retry. The rescue_block actions need to apply to the loop, not itself.

EDIT:

Using Twitter gem, most of Twitter's errors can be handled the same way (i.e. if you hit the API limit, wait.). Full code:

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

Upvotes: 0

Views: 8334

Answers (1)

Joshua Cheek
Joshua Cheek

Reputation: 31746

Your example makes it look like you want macros, which Ruby doesn't have.

We can get pretty close to your example with blocks, but it is really difficult to answer this without knowing your use case. (I imagine you aren't using exceptions for flow control, this is typically frowned upon as flow control isn't an exceptional situation).

Depending on what you're trying to do, throw and catch may be better suited to your needs than exceptions.

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

Upvotes: 3

Related Questions