こんにちは、 id:rightgo09 です。
比較演算子の左右とコメントの罠に嵌ったのでエントリの一つとして書いてみます。
弊社のRuby on Railsのプログラムで以下のようなコードがありました(例です)。
# @param [Date] date # @return [Boolean] def future?(date) date > Date.today end
これを以下のように変更しました。
# @param [Date] date # @return [Boolean] def future?(date) - date > Date.today + Date.today < date end
すると、ステージング環境で例外が発生する事象に遭遇しました。
ArgumentError (comparison of Date with ActiveSupport::TimeWithZone failed)
デバッグしてみると、このメソッドを呼び出しているひとつが、引数に Dateオブジェクトではなく ActiveSupport::TimeWithZoneオブジェクトを渡していることがわかりました。
ActiveSupport::TimeWithZoneとDateの比較
ActiveSupport::TimeWithZoneとDateを比較する際は、左辺と右辺に注意する必要があります。
now = Time.zone.now now.class #=> ActiveSupport::TimeWithZone today = Date.today today.class #=> Date # OK # 左辺:ActiveSupport::TimeWithZone # 右辺:Date now < today #=> false # NG # 左辺:Date # 右辺:ActiveSupport::TimeWithZone today < now #=> ArgumentError: comparison of Date with ActiveSupport::TimeWithZone failed
Dateオブジェクトが左辺に来る場合、右辺として比較可能なのは、以下の2つです。
- Dateオブジェクト
- ユリウス通日を表す数値(時刻付きならRational)
ActiveSupport::TimeWithZoneオブジェクトを左辺におくと、utcメソッドが呼ばれてTimeオブジェクトとなるため、Dateオブジェクトとも比較が可能なようです。
まとめ
今回のことから以下のことを学びました。
- Dateオブジェクトが左辺にくるときは気をつける
- 動的言語で、時代を感じるプログラムでは、型を示唆するコメントは信用しない
以上です。