Ruby Language                
            例外
        
        
            
    サーチ…
備考
例外は、例外条件の発生を表すオブジェクトです。つまり、何かが間違っていたことを示しています。
 Rubyでは、 例外はしばしばエラーと呼ばれます。これは、基本Exceptionクラスがトップレベルの例外オブジェクト要素として存在するためですが、ユーザー定義の実行例外は一般にStandardErrorまたは子孫です。 
例外を発生させる
例外を発生させるには、 Kernel#raiseが例外クラスおよび/またはメッセージを渡します: 
raise StandardError # raises a StandardError.new
raise StandardError, "An error" # raises a StandardError.new("An error")
単にエラーメッセージを渡すこともできます。この場合、メッセージはRuntimeErrorラップされます。 
raise "An error" # raises a RuntimeError.new("An error")
ここに例があります:
def hello(subject)
  raise ArgumentError, "`subject` is missing" if subject.to_s.empty?
  puts "Hello #{subject}"
end
hello # => ArgumentError: `subject` is missing
hello("Simone") # => "Hello Simone"
カスタム例外タイプの作成
カスタム例外を拡張するすべてのクラスであるExceptionまたはサブクラスのException 。 
通常、 StandardErrorまたはその子孫を拡張する必要があります。 Exceptionファミリは通常、仮想マシンエラーまたはシステムエラーのために救済され、強制的な中断が予想通りに機能しないようにすることができます。 
# Defines a new custom exception called FileNotFound
class FileNotFound < StandardError
end
def read_file(path)
  File.exist?(path) || raise(FileNotFound, "File #{path} not found")
  File.read(path)
end
read_file("missing.txt")  #=> raises FileNotFound.new("File `missing.txt` not found")
read_file("valid.txt")    #=> reads and returns the content of the file
最後にErrorサフィックスを追加することで、例外に名前を付けるのが一般的です。 
-  ConnectionError
-  DontPanicError
ただし、エラーが自明である場合、冗長であるため、 Errorサフィックスを追加する必要はありません。 
-  FileNotFoundとFileNotFoundError
-  DatabaseExplodedとDatabaseExplodedError
例外の処理
 begin/rescueブロックを使用して例外を捕捉(レスキュー)し、それを処理します。 
begin
  # an execution that may fail
rescue
  # something to execute in case of failure
end
 rescue句は、C#やJavaなどの中括弧で囲まれたcatchブロックに似ています。 
このような裸のrescueはStandardError救う。 
注意:デフォルトのStandardError代わりにExceptionをキャッチしないよう注意してください。 ExceptionクラスにはSystemExitとNoMemoryError含まれ、通常はキャッチしたくない重大な例外があります。代わりに、常にStandardError (デフォルト)をキャッチすることを検討してください。 
レスキューする必要がある例外クラスを指定することもできます。
begin
  # an excecution that may fail
rescue CustomError
  # something to execute in case of CustomError
  # or descendant
end
このレスキュー句は、 CustomErrorではない例外をキャッチしません。 
特定の変数に例外を格納することもできます。
begin
  # an excecution that may fail
rescue CustomError => error
  # error contains the exception
  puts error.message # provide human-readable details about what went wrong.
  puts error.backtrace.inspect # return an array of strings that represent the call stack
end
例外処理に失敗した場合は、レスキューブロックでいつでも例外を発生させることができます。
begin
   #here goes your code
rescue => e
    #failed to handle 
    raise e
end
あなたが再試行したい場合はbeginブロックを、呼び出しretry : 
begin
   #here goes your code
rescue StandardError => e
   #for some reason you want to retry you code
   retry
end
再試行ごとに例外を検出すると、ループに陥る可能性があります。これを避けるには、 retry_countを特定の試行回数に制限します。 
retry_count = 0
begin
      # an excecution that may fail
rescue
    if retry_count < 5
        retry_count = retry_count + 1
        retry
    else
        #retry limit exceeds, do something else
    end
 elseブロックまたはensureブロックを指定することもできます。 elseブロックは、例外がスローされずにbeginブロックが完了したときに実行されます。 ensureブロックは常に実行されます。 ensureブロックは、C#やJavaのような中括弧のfinallyブロックに似ています。 
begin
  # an execution that may fail
rescue
  # something to execute in case of failure
else
  # something to execute in case of success
ensure
  # something to always execute
end
 def 、 moduleまたはclassブロックの内部にある場合は、begin文を使用する必要はありません。 
def foo
    ...
rescue
    ...
end
複数の例外の処理
同じrescue宣言で複数のエラーを処理することができます: 
begin
  # an execution that may fail
rescue FirstError, SecondError => e
  # do something if a FirstError or SecondError occurs
end
複数のrescue宣言を追加することもできます。 
begin
  # an execution that may fail
rescue FirstError => e
  # do something if a FirstError occurs
rescue SecondError => e
  # do something if a SecondError occurs
rescue => e
  # do something if a StandardError occurs
end
 rescueブロックの順序は関係します。最初の一致は実行されたものです。したがって、 StandardErrorを最初の条件として置き、すべての例外がStandardErrorから継承する場合、他のrescueステートメントは決して実行されません。 
begin
  # an execution that may fail
rescue => e
  # this will swallow all the errors
rescue FirstError => e
  # do something if a FirstError occurs
rescue SecondError => e
  # do something if a SecondError occurs
end
いくつかのブロックはdef 、 class 、 moduleような暗黙の例外処理を持っていmodule 。これらのブロックを使用すると、 begin文をスキップできます。 
def foo
    ...
rescue CustomError
    ...
ensure
    ...
end
(カスタム)例外への情報の追加
例えば、ロギング目的で、または例外がキャッチされたときに条件付き処理を許可するために、例外とともに追加情報を含めると便利です。
class CustomError < StandardError
  attr_reader :safe_to_retry
  def initialize(safe_to_retry = false, message = 'Something went wrong')
    @safe_to_retry = safe_to_retry
    super(message)
  end
end
例外を発生させる:
raise CustomError.new(true)
例外をキャッチし、提供された追加情報にアクセスする:
begin
  # do stuff
rescue CustomError => e
  retry if e.safe_to_retry
end