Skip to content

Commit 5450270

Browse files
authored
Merge pull request rails#39255 from kamipo/fix_min_and_max_on_tz_aware_attributes
Fix `minimum` and `maximum` on time zone aware attributes
2 parents 2138614 + 11751b2 commit 5450270

File tree

3 files changed

+48
-14
lines changed

3 files changed

+48
-14
lines changed

activerecord/CHANGELOG.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,6 @@
6262

6363
*Ryuta Kamizono*
6464

65-
* Fix aggregate functions to return numeric value consistently even on custom attribute type.
66-
67-
*Ryuta Kamizono*
68-
6965
* Support bulk insert/upsert on relation to preserve scope values.
7066

7167
*Josef Šimánek*, *Ryuta Kamizono*

activerecord/lib/active_record/relation/calculations.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,7 @@ def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
307307
result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
308308

309309
type_cast_calculated_value(result.cast_values.first, operation) do |value|
310-
if value.is_a?(String) &&
311-
column = klass.columns_hash[column_name.to_s]
312-
type = connection.lookup_cast_type_from_column(column)
310+
if type = klass.attribute_types[column_name.to_s]
313311
type.deserialize(value)
314312
else
315313
value
@@ -379,9 +377,7 @@ def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
379377
key = key_records[key] if associated
380378

381379
result[key] = type_cast_calculated_value(row[column_alias], operation) do |value|
382-
if value.is_a?(String) &&
383-
(type || column = klass.columns_hash[column_name.to_s])
384-
type ||= connection.lookup_cast_type_from_column(column)
380+
if type ||= klass.attribute_types[column_name.to_s]
385381
type.deserialize(value)
386382
else
387383
value

activerecord/test/cases/calculations_test.rb

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,12 +1044,12 @@ def test_group_by_attribute_with_custom_type
10441044
def test_aggregate_attribute_on_custom_type
10451045
assert_equal 4, Book.sum(:status)
10461046
assert_equal 1, Book.sum(:difficulty)
1047-
assert_equal 0, Book.minimum(:status)
1048-
assert_equal 1, Book.maximum(:difficulty)
1047+
assert_equal "easy", Book.minimum(:difficulty)
1048+
assert_equal "medium", Book.maximum(:difficulty)
10491049
assert_equal({ "proposed" => 0, "published" => 4 }, Book.group(:status).sum(:status))
10501050
assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).sum(:difficulty))
1051-
assert_equal({ "proposed" => 0, "published" => 2 }, Book.group(:status).minimum(:status))
1052-
assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).maximum(:difficulty))
1051+
assert_equal({ "proposed" => "easy", "published" => "easy" }, Book.group(:status).minimum(:difficulty))
1052+
assert_equal({ "proposed" => "easy", "published" => "medium" }, Book.group(:status).maximum(:difficulty))
10531053
end
10541054

10551055
def test_minimum_and_maximum_on_non_numeric_type
@@ -1059,6 +1059,48 @@ def test_minimum_and_maximum_on_non_numeric_type
10591059
assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).maximum(:last_read))
10601060
end
10611061

1062+
def test_minimum_and_maximum_on_time_attributes
1063+
assert_minimum_and_maximum_on_time_attributes(Time)
1064+
end
1065+
1066+
def test_minimum_and_maximum_on_tz_aware_attributes
1067+
with_timezone_config aware_attributes: true, zone: "Pacific Time (US & Canada)" do
1068+
Topic.reset_column_information
1069+
assert_minimum_and_maximum_on_time_attributes(ActiveSupport::TimeWithZone)
1070+
end
1071+
ensure
1072+
Topic.reset_column_information
1073+
end
1074+
1075+
def assert_minimum_and_maximum_on_time_attributes(time_class)
1076+
actual = Topic.minimum(:written_on)
1077+
assert_equal Time.utc(2003, 7, 16, 14, 28, 11, 223300), actual
1078+
assert_instance_of time_class, actual
1079+
1080+
actual = Topic.maximum(:written_on)
1081+
assert_equal Time.utc(2013, 7, 13, 11, 11, 0, 9900), actual
1082+
assert_instance_of time_class, actual
1083+
1084+
expected = {
1085+
false => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
1086+
true => Time.utc(2004, 7, 15, 14, 28, 0, 9900),
1087+
}
1088+
actual = Topic.group(:approved).minimum(:written_on)
1089+
assert_equal expected, actual
1090+
assert_instance_of time_class, actual[true]
1091+
assert_instance_of time_class, actual[true]
1092+
1093+
expected = {
1094+
false => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
1095+
true => Time.utc(2013, 7, 13, 11, 11, 0, 9900),
1096+
}
1097+
actual = Topic.group(:approved).maximum(:written_on)
1098+
assert_equal expected, actual
1099+
assert_instance_of time_class, actual[true]
1100+
assert_instance_of time_class, actual[true]
1101+
end
1102+
private :assert_minimum_and_maximum_on_time_attributes
1103+
10621104
def test_select_avg_with_group_by_as_virtual_attribute_with_sql
10631105
rails_core = companies(:rails_core)
10641106

0 commit comments

Comments
 (0)