raise で例外クラスにパラメーターを与える
2016-09-27
解決したいコード
例えば、CSV ファイルから何かしらのデータを transaction
でインポートする時に「23行目の2列目でエラーが発生しました。」といったエラーメッセージを発行したいとする。
class CsvImportError < StandardError; end
raise CsvImportError, I18n.t('error_csv_import', row: row, col: col)
こうすると、エラーメッセージの内容まで CSV のインポートクラスが背負う羽目になり、エラーの種類やメッセージの複雑度が増えてきた時に、プログラマーが辛みを背負うことになる。
1つの解決策
raise
の第一引数には例外クラスのインスタンスを渡すことができるので、以下のように書くことができる。
class CsvImportError < StandardError
def initialize(row, col)
super I18n.t('error_csv_import', row: row, col: col)
end
end
raise CsvImportError.new(row, col)
ただ、利用側のコードで明示的に例外クラスのインスタンス化を見せられるのは少し辛い。
もう1つの解決策
raise
の第二引数は例外クラスのイニシャライザーに渡されるのを利用して、下記のように書くことができる。
class CsvImportError < StandardError
def initialize(row:, col:)
super I18n.t('error_csv_import', row: row, col: col)
end
# あるいは呼び出し側にパラメーターを託しても良い
# def initialize(params)
# super I18n.t('error_csv_import', params)
# end
end
raise CsvImportError, row: row, col: col
Ruby は第二引数に String
のメッセージを期待していると思うが、 { row: row, col: col }
という Hash
を渡している。動的型付けとキーワード引数の特性を利用した、少しハックじみたアプローチではあるが、 raise 例外クラス, パラメータのHash
という文法で書けるのは少し嬉しい。