Mongoidを使っているRailsアプリを、Rails4から5にあげるときに奇妙なことが起きた。
Rails4から5にあげるのに伴って、Mongoidを5.xから6.xに更新したのだが、テストが通らなくなった。
問題の箇所を抜粋すると以下のようなコードになる。
my_model.rb
class MyModel
include Mongoid::Document
field :key, type: String
field :default, type: String
field :format, type: String
validates :key, presence: true, uniqueness: true, format: {with: /\A\w+\z/}
validate :default_value_conform_to_format
private
def default_value_conform_to_format
regexp = Regexp.new(self.format.to_s)
unless regexp =~ self.default.to_s
errors.add(:default, "does not match regexp #{self.format}")
end
end
end
Mongoidを6にあげるとdefault_value_conform_to_format
でvalidationエラーが発生するようになる。
ちなみにテストケースでは、default
もformat
もどちらもnilになっている。
空の正規表現は、空文字列にマッチするはずなので、エラーが起きるはずはないと思っていた。
// =~ "" #=> 0
問題となっていたのは、実はRubyの標準ライブラリのRegexp
ではなくて、Mongoidの中のMongoid::Matchable::Regexp
というクラスを参照するように変わってしまっていたことだった。
どうやらMongoidが勝手にこのような名前のクラスを追加してしまっていたようだ。しかもタチの悪いことに標準のRegexp
と挙動が異なる。
- regexp = Regexp.new(self.format.to_s)
+ regexp = ::Regexp.new(self.format.to_s)
としたところ解決した。