retryable gemでretry回数を指定したrescueを簡単に

（旧タイトル：rescue節での上限回数付きretry（retryカウンタをbegin以前に宣言せずに））
#便利なGemをご紹介頂きました。
もともとの記事のコメント欄で @pasela さんに
>retryableというgemを使うとスッキリ書けると思います。

とご紹介頂きました。
ソースが短いので、読んで使い方をまとめてみました（間違っていたらご指摘ください）。
大元の記事はオマケに成り下がりましたw
#retryableの使い方（v1.3.5）
（**注：[v2.0.0以上](https://github.com/nfedyashev/retryable/commit/33e6e396016705b4ac00e18fc0f36a20704d35f7)からメソッドが `Kernel.#retryable` から `Retryable.retryable` に変更されました。以下の記載はv1.3.5時点の記事なので読み替えてください。**）
`require 'retryable'`します。
`Kernel.#retryable`に渡すブロックで、例外時にretryする処理を指定します。
具体例は @pasela さんが書いてくださった[コメント欄](http://qiita.com/riocampos/items/b2bf78c5e37280a1f8ff#comment-afbab53fd05d70de2ea6)や、[retryableのRubyDoc](http://rubydoc.info/gems/retryable/)
をご覧ください。
##`Kernel.#retryable`の仮引数Hash
###繰り返し回数指定：`:tries`
デフォルト値 n=2 。
>Should an exception occur, it'll retry for (n-1) times.

###スリープ秒数：`:sleep`
デフォルト値 1秒。
引数には数字またはProcオブジェクトが取れます。
>`retryable(:sleep => lambda { |n| 4**n }) { }   # sleep 1, 4, 16, etc. each try
`

###捕捉する例外を指定：`:on`または`:matching`
大まかに`:on`で捕捉する例外を指定して`:matching`の正規表現で実際に例外捕捉するようです。
`:matching`を指定しなければ`:on`を満たす例外が捕捉されます。
`:on`を指定しなければ、`:on`のデフォルト値`StandardError`に含まれた例外のうち`:matching`を満たす例外が捕捉されます。
###例外捕捉時処理の指定：`:exception_cb`
Procオブジェクトで渡します。引数には例外名が渡されます。
###後処理の指定：`:ensure`
Procオブジェクトで渡します。引数にはリトライ回数が渡されます。
###<del>ログ出力指定：`:task`</del>
<del>`:task`に処理名称を入れると、名称・リトライ回数・捕捉された例外名をログで表示します。</del>
これ無くなってます（GithubのREADME.markdownにはまだ残ってますが）。
おそらく、リトライ回数と例外名が`Kernel.#retryable`のブロックパラメータへ渡せるので、ログ書くならご自由に、というような事ではないでしょうか。

>```rb
retryable do |retries, exception|
  puts "try #{retries} failed with exception: #{exception}" if retries > 0
  pick_up_soap
end
```

##関連リンク
* [retryable | RubyGems.org | your community gem host](http://rubygems.org/gems/retryable)
* [File: README — Documentation for retryable](http://rubydoc.info/gems/retryable/)
* ~~[bronson/retryable](https://github.com/bronson/retryable)~~ [nfedyashev/retryable](https://github.com/nfedyashev/retryable)
* [Facebookから社内ADまで、外部サービスと連携するときに知っておくと役に立つライブラリ - よかろうもん！](http://interu.hatenablog.com/entry/20120404/1333546980)

<hr>
以下は元記事です。
#核となる部分
カウンタの初期化と加算とを行う`_retry = (_retry || 0) + 1`というイディオムがポイント。

```ruby
retry_upto = 5 # retry回数の上限

begin
  something_do_with_error()
rescue => e
  #カウンタの初期化、加算、上限確認
  if _retry = (_retry || 0) + 1 and _retry < retry_upto
    retry
  else
    #カウンタを念のためにリセット
    _retry = nil
    raise e
  end
end
```
#具体例
あまり上手い例ではないですスミマセン。

```rb
retry_upto = 5

test = lambda {
  loop do
    begin
      print (r = rand(10))
      #rが0..6ならばraise、7..9ならばputs r
      if r <= 6
        raise 
      else
        puts
      end
    rescue => e
      print " -> retry: "
      if _retry = (_retry || 0) + 1 and _retry < retry_upto
        puts _retry
        retry
      else
        _retry = nil
        raise e
      end
    end
  end
}
```
##実行結果例

```rb
> test.call
6 -> retry: 1
6 -> retry: 2
5 -> retry: 3
9
4 -> retry: 4
5 -> retry: RuntimeError: 

> test.call
0 -> retry: 1
1 -> retry: 2
4 -> retry: 3
1 -> retry: 4
2 -> retry: RuntimeError: 

> test.call
7
0 -> retry: 1
5 -> retry: 2
4 -> retry: 3
8
0 -> retry: 4
9
3 -> retry: RuntimeError: 
```

#参考
本質的にこれをそのまま利用しています。
このやり方うまいなーと思いつつ、そのままブラウザのタブに残してたままにしてました。
そろそろタブを消したいのでQiitaにメモ書きしましたw

>```rb
begin
  @browser = Watir::Browser.new :phantomjs, :http_client => client
rescue Selenium::WebDriver::Error::WebDriverError => e
  sleep 0.3
  if _r = (_r || 0) + 1 and _r < 5
    retry
  else
    raise e
  end
end
```
[can't create browser object for phantomjs · Issue #222 · watir/watir-webdriver](https://github.com/watir/watir-webdriver/issues/222#issuecomment-27783207)

##以前書いた関連Qiita投稿
[Ruby - rescue 節で一定回数 retry したあとは次に移るループ - Qiita](http://qiita.com/riocampos/items/0870f1b682a62d6477de)
これを書いたあとに上記の書き方を知りました。