retryableというgemがあります。
キーワード引数matching
を使って捕捉する例外を指定することができます。
def retryable(tries:, matching: StandardError)
begin
# なんらかのテクニックが必要
rescue *matching => e # このままでは動かない
puts e.message
end
end
ここで話題にしたいのはmatching
には例外クラスを配列で指定するか、
例外クラスを1つだけのどちらでも使えるようにするテクニックです。
rescue
で例外を捕捉する必要がありますので1次元配列(入れ子でない)にする必要があります。
私がおもいついたのは3つです。retryable
ではflatten
を利用しているようです。
matching = matching.is_a?(Array) ? matching : [matching]
matching = [matching].flatten
matching = Array[*matching]
これらのベンチマークを取ってみました。
require 'benchmark_driver'
Benchmark.driver do |x|
x.prelude %{ array = [*1..5000] }
x.report "flatten", %{ [array].flatten }
x.report "using Array.[]", %{ Array[*array] }
x.report "Object#is_a?", %{ array.is_a?(Array) ? array : [array] }
x.compare!
end
なんと結果はflatten
が一番遅いことがわかりました
Warming up --------------------------------------
flatten 1.869k i/s
using Array.[] 56.587k i/s
Object#is_a? 16.534M i/s
Calculating -------------------------------------
flatten 2.029k i/s - 5.607k times in 2.763675s (492.90μs/i)
using Array.[] 54.798k i/s - 169.760k times in 3.097910s (18.25μs/i)
Object#is_a? 30.039M i/s - 49.602M times in 1.651260s (33.29ns/i)
Comparison:
Object#is_a?: 30038651.1 i/s
using Array.[]: 54798.2 i/s - 548.17x slower
flatten: 2028.8 i/s - 14805.97x slower
ということでPRを本家に出しました
マージされるといいなぁ