Ruby: 定数に再代入したら例外を発生させる
背景
Rubyでは定数に再代入した場合、warningは出るが処理がとまることはない。 警告メッセージだけだと見逃すことがあるので例外を発生させたい。
Ruby本来の動作
a.rb
DUP = 'file a'
b.rb
DUP = 'file b'
main.rb
require_relative 'a' require_relative 'b'
上記のようなファイル構成のときmain.rbを実行すると以下のような出力になる。
出力
b.rb:1: warning: already initialized constant DUP a.rb:1: warning: previous definition of DUP was here
解決策
GitHub - jeremyevans/ruby-warning: Add custom processing for warnings
このwarningというgemを導入すると Warning.ignore
という特定の警告を非表示にする機能と Warning.process
という警告をキャッチして任意の処理を実行する機能が使えるようになる。
今回は Warning.process
を使いmain.rbを以下のように書き換え、定数上書きの警告メッセージをキャッチして例外を発生させるようにする。
main.rb
require 'warning' Warning.process do |warning| next :raise if warning.match?(/previous definition of \w+ was here/) :default end require_relative 'a' require_relative 'b'
出力
b.rb:1: warning: already initialized constant DUP Traceback (most recent call last): 3: from b:10:in `<main>' 2: from b:10:in `require_relative' 1: from b.rb:1:in `<top (required)>' ~/.gem/ruby/2.7.0/gems/warning-1.1.0/lib/warning.rb:213:in `warn': a.rb:1: warning: previous definition of DUP was here (RuntimeError)
Warning.process
のブロック引数には警告メッセージの文字列が渡される。
このブロックは戻り値が :raise
のとき例外を発生させる。
戻り値が :default
の場合は本来の挙動と同じく警告メッセージを出力する。
定数上書き時は2つのメッセージが出るが、1つ目で例外を発生させてしまうと、片方のメッセージしか表示されず原因が分かりづらくなるので少し注意が必要だ。