Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7.1: Object#inでbeginless/endlessの日付rangeがサポートされる(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

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をサポート(翻訳)

Rails 7: Ruby 2.7の"beginless range"がサポートされる(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。