Railsの技: 日付同士をbefore?とafter?で比較する(翻訳)
私は日付同士を比較するコードを書くときに、わけもなく緊張してしまいます。気をつけていないと<
や>=
の向きを取り違えて逆に書いてしまいがちなのです。
私は日付の比較を「より前(before)」か「より後(after)」で考えるので、たとえばstart_date
はend_date
「より大きい(greater than)か」あるいは「より小さい(less than)か」という発想に置き換えようとすると混乱してしまいます。
使い方
ありがたいことに、私が二度とこのような失敗をしないように、Railsはすべての日付関連の比較にbefore?
メソッドとafter?
メソッドを追加してくれています。おかげさまで私のような者にとっては助かります。
start_date = Date.new(2019, 3, 31)
end_date = Date.new(2019, 4, 1)
start_date.before? end_date
#=> true
end_date.after? start_date
#=> true
start_date = Date.new(2020, 8, 11)
end_date = Date.new(2018, 8, 11)
start_date.before? end_date
#=> false
気がつくと私は、以下のようにRailsのモデルで日付同士が有効範囲に収まっているかどうかをバリデーションするときにbefore?
とafter?
を愛用するようになりました。
class Promotion < ApplicationRecord
validate :valid_eligiblity_range?
def valid_eligiblity_range?
return unless expiration_date? && start_date?
if !expiration_date.after?(start_date)
errors.add(:start_date, "must be before Expiration Date")
errors.add(:expiration_date, "must be after Start Date")
end
end
end
参考資料
- Rails APIドキュメント:
DateAndTime::Calculations#before?
-
Rails APIドキュメント:
DateAndTime::Calculations#after?
概要
原著者の許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。