You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Create a table with a postgres date range column (tsrange for example)
Create an entry in that table witha date range that has infinity on one end and save it range_test = RangeTest.create!(date_range: (DateTime.new(2024,1,1)...DateTime::Infinity.new))
Reload that entry from the database (deserialize it) range_test.reload
Look at the infinite part of the range now and it no longer is infinite... it is nil puts range_test.date_rage.end.class returns NilClass
In previous version of rails (7.0.8 for example), it actuallly returned a Float::INFINITY class... this was a little off, but closer to the mark than nil.
At least with that, we could to a check like date_range.end.to_s == 'Infinity' in our logic, which looks reasonable
require"bundler/inline"gemfile(true)dosource"https://rubygems.org"git_source(:github){ |repo| "https://github.com/#{repo}.git"}# gem "rails", '= 7.0.8'gem"rails",'~> 7.1.3'# If you want to test against edge Rails replace the previous line with this:# gem "rails", github: "rails/rails", branch: "main"gem"pg"endrequire"active_record"require"minitest/autorun"require"logger"# You may need to change your pg settings accordinglydb_config={adapter: 'postgresql',database: 'range_test',host: '::1',# Change this to your PostgreSQL hostport: 5432,username: 'postgres',# Change this to your PostgreSQL usernamepassword: 'test'# Change this to your PostgreSQL password}beginActiveRecord::Base.establish_connection(db_config.except(:database))ActiveRecord::Base.connection.drop_database(db_config[:database])rescuenilActiveRecord::Base.connection.create_database(db_config[:database])endActiveRecord::Base.establish_connection(db_config)ActiveRecord::Base.logger=Logger.new(STDOUT)ActiveRecord::Schema.definedocreate_table:range_testsdo |t|
t.tsrange:date_ranget.timestampsendendclassRangeTest < ActiveRecord::BaseendclassBugTest < Minitest::Testdeftest_date_range_infinity_deserializationrange=(DateTime.new(2024,1,1)...DateTime::Infinity.new)range_test=RangeTest.create!(date_range: range)assert_equalDateTime::Infinity,range_test.date_range.end.class# Need to reload to deserialize the range back out from the DB to see the problemrange_test.reload# Interestingly, even before rails 7.1.3, the end range would deserialize to a Float::INFINITY# So we're checking the to_s representation to show the change in behaviorassert_equal"Infinity",range_test.date_range.end.to_sendend
Expected behavior
Frankly, it was a bit of a bug before in that this would return a Float::INFINITY object before, where it should have returned a DateTime::INFINITY. At least with that you could, for example, check date_range.end.to_s == 'Infinity' for some kind of logical checking for an infinite range start or end.
Returning nil seems to be undocumented change in behavior at the very least.
Actual behavior
The date range returns a nil object for whichever end of the range may be infinite.
System configuration
Rails version: 7.1.3
Ruby version: 3.2.2
The text was updated successfully, but these errors were encountered:
That was changed in #45099. So I would say that this is expected behavior - the postgres adapter correctly returns an infinite range. Its just unfortunate that ruby represents one of its ends as nil.
I think this change is for the better, but it is a change. Even though that (Date.today...) and (Date.today...Float::INFINITY) can be the same thing, there is a weird mismatch in types, once is a date and the other is a float. To me the natural way to write unbounded ranges is (1..).
Steps to reproduce
range_test = RangeTest.create!(date_range: (DateTime.new(2024,1,1)...DateTime::Infinity.new))
range_test.reload
puts range_test.date_rage.end.class
returnsNilClass
In previous version of rails (7.0.8 for example), it actuallly returned a Float::INFINITY class... this was a little off, but closer to the mark than nil.
At least with that, we could to a check like
date_range.end.to_s == 'Infinity'
in our logic, which looks reasonableExpected behavior
Frankly, it was a bit of a bug before in that this would return a Float::INFINITY object before, where it should have returned a DateTime::INFINITY. At least with that you could, for example, check
date_range.end.to_s == 'Infinity'
for some kind of logical checking for an infinite range start or end.Returning nil seems to be undocumented change in behavior at the very least.
Actual behavior
The date range returns a nil object for whichever end of the range may be infinite.
System configuration
Rails version: 7.1.3
Ruby version: 3.2.2
The text was updated successfully, but these errors were encountered: