开发者

ruby: how to know if script is on 3rd retry?

begin
#some routine
rescue
retry
#on third retry, output "no dice!"
end

I want to make开发者_运维问答 it so that on the "third" retry, print a message.


Possibly not the best solution, but a simple way is just to make a tries variable.

tries = 0
begin
  # some routine
rescue
  tries += 1
  retry if tries <= 3
  puts "no dice!"
end


loop do |i|
  begin
    do_stuff
    break
  rescue
    raise if i == 2
  end
end

or

k = 0
begin
  do_stuff
rescue    
  k += 1
  k < 3 ? retry : raise
end


begin
  #your code
rescue
  retry if (_r = (_r || 0) + 1) and _r < 4  # Needs parenthesis for the assignment
  raise
end


There is another gem named retry-this that helps with such a thing.

ruby-1.9.2-p0 > require 'retry-this'
ruby-1.9.2-p0 > RetryThis.retry_this(:times => 3) do |attempt|
ruby-1.9.2-p0 >     if attempt == 3
ruby-1.9.2-p0 ?>      puts "no dice!"
ruby-1.9.2-p0 ?>    else
ruby-1.9.2-p0 >       puts "trying something..."
ruby-1.9.2-p0 ?>      raise 'an error happens' # faking a consistent error
ruby-1.9.2-p0 ?>    end
ruby-1.9.2-p0 ?>  end
trying something...
trying something...
no dice!
 => nil 

The good thing about such a gem as opposed to raw begin..rescue..retry is that we can avoid an infinite loop or introducing a variable just for this purpose.


class Integer
  def times_try
    n = self
    begin
      n -= 1
      yield
    rescue
      raise if n < 0
      retry
    end
  end
end

begin
  3.times_try do
    #some routine
  end
rescue
  puts 'no dice!'
end


The gem attempt is designed for this, and provides the option of waiting between attempts. I haven't used it myself, but it seems to be a great idea.

Otherwise, it's the kind of thing blocks excel at, as other people have demonstrated.


def method(params={})
  tries ||= 3
  # code to execute
rescue Exception => e
  retry unless (tries -= 1).zero?
  puts "no dice!"
end


Proc.class_eval do
  def rescue number_of_attempts=0
    @n = number_of_attempts
      begin
        self.call 
      rescue => message
        yield message, @n if block_given?
        @n -= 1
        retry if @n > 0
      end
    end
end

And then you can use it as:

-> { raise 'hi' }.rescue(3)
-> { raise 'hi' }.rescue(3) { |m, n| puts "message: #{m}, 
                                           number of attempts left: #{n}" }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜