Rails 7.1: Object#inでbeginless/endlessの日付rangeがサポートされる(翻訳)
Object#in?(別のオブジェクト)
メソッドは、Rubyの標準ライブラリに含まれていません。これはRailsによってObject
クラスに追加された便利なメソッドであり、オブジェクトが別のオブジェクトに含まれているかどうかをチェックするのに使われます。
このメソッドは、呼び出し元のオブジェクトが引数内に見つかった場合にtrue
を返します。この引数には任意のオブジェクトを渡せますが、#include?
メソッドに応答しなければなりません。これは、特定の要素がコレクションやデータ構造に含まれているかどうかをチェックするのに使う一般的なメソッドです。
fruits = ["Apple", "Mango", "Orange"]
"Apple".in?(fruits) # => true
🔗 改修前
Object#in?
では、文字列、数値、ハッシュなどのオブジェクトは正しく検証できます。しかしRuby 3.1では、オープンな(=いわゆるbeginlessやendlessを含む)日付rangeに存在するかどうかをチェックするのに使うと無限ループになるため、結果が得られませんでした。また、Ruby 3.2ではTypeError
が発生しました。
irb(main):001:0> Date.today.in?(Date.tomorrow..)
#=> .rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.0.4.3/lib/active_support/core_ext/range/compare_range.rb:51:in
#`include?': cannot determine inclusion in beginless/endless ranges (TypeError)
irb(main):002:0>
指定の日付がオープンな日付rangeに存在するかどうかを確認するためには、cover?
メソッドを使う必要がありました。cover?
メソッドは、日付がそのrange内にある場合はtrue
を返し、それ以外の場合はfalse
を返します。
((Date.today + 1)..).cover?(Date.today) #=> false, immediately
🔗 改修後
次期バージョンのRailsでは、日付がオープンな日付rangeに存在するかどうかをObject#in?
で確認できるようになります。
#47316の変更によって、Object#in?
がオープンな日付range(beginlessやendless)を正しく扱えるようになります。
Object#in?
の内部では、Range#cover?
を使うことで、開始日付または終了日付がない以下のような日付rangeの包含チェックを適切に処理します。
Date.today.in?(Date.tomorrow..) #=> false
((Date.today + 1)..).in?(Date.today..) #=> true
関連記事
Rails 7.1: Active Modelバリデーションのin・withinオプションでbeginless/endless rangeをサポート(翻訳)
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。