mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #39111 from kamipo/fix_min_and_max_on_non_numeric_column
Fix `minimum` and `maximum` on non numeric column
This commit is contained in:
commit
483330eeea
2 changed files with 48 additions and 13 deletions
|
@ -304,8 +304,17 @@ module ActiveRecord
|
|||
query_builder = relation.arel
|
||||
end
|
||||
|
||||
value = skip_query_cache_if_necessary { @klass.connection.select_value(query_builder) }
|
||||
type_cast_calculated_value(value, operation)
|
||||
result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
|
||||
|
||||
type_cast_calculated_value(result.cast_values.first, operation) do |value|
|
||||
if value.is_a?(String) &&
|
||||
column = klass.columns_hash[column_name.to_s]
|
||||
type = connection.lookup_cast_type_from_column(column)
|
||||
type.deserialize(value)
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
|
||||
|
@ -351,17 +360,33 @@ module ActiveRecord
|
|||
key_records = key_records.index_by(&:id)
|
||||
end
|
||||
|
||||
calculated_data.each_with_object({}) do |row, result|
|
||||
key = group_columns.map { |aliaz, col_name|
|
||||
type = type_for(col_name) do
|
||||
calculated_data.column_types.fetch(aliaz, Type.default_value)
|
||||
end
|
||||
type.deserialize(row[aliaz])
|
||||
}
|
||||
key_types = group_columns.each_with_object({}) do |(aliaz, col_name), types|
|
||||
types[aliaz] = type_for(col_name) do
|
||||
calculated_data.column_types.fetch(aliaz, Type.default_value)
|
||||
end
|
||||
end
|
||||
|
||||
hash_rows = calculated_data.cast_values(key_types).map! do |row|
|
||||
calculated_data.columns.each_with_object({}).with_index do |(column, hash), i|
|
||||
hash[column] = row[i]
|
||||
end
|
||||
end
|
||||
|
||||
type = nil
|
||||
hash_rows.each_with_object({}) do |row, result|
|
||||
key = group_aliases.map { |aliaz| row[aliaz] }
|
||||
key = key.first if key.size == 1
|
||||
key = key_records[key] if associated
|
||||
|
||||
result[key] = type_cast_calculated_value(row[column_alias], operation)
|
||||
result[key] = type_cast_calculated_value(row[column_alias], operation) do |value|
|
||||
if value.is_a?(String) &&
|
||||
(type || column = klass.columns_hash[column_name.to_s])
|
||||
type ||= connection.lookup_cast_type_from_column(column)
|
||||
type.deserialize(value)
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -389,9 +414,12 @@ module ActiveRecord
|
|||
|
||||
def type_cast_calculated_value(value, operation)
|
||||
case operation
|
||||
when "sum" then value || 0
|
||||
when "average" then value&.respond_to?(:to_d) ? value.to_d : value
|
||||
else value
|
||||
when "count", "sum"
|
||||
value || 0
|
||||
when "average"
|
||||
value&.respond_to?(:to_d) ? value.to_d : value
|
||||
else # "minimum", "maximum"
|
||||
yield value
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1023,6 +1023,13 @@ class CalculationsTest < ActiveRecord::TestCase
|
|||
assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).maximum(:difficulty))
|
||||
end
|
||||
|
||||
def test_minimum_and_maximum_on_non_numeric_type
|
||||
assert_equal Date.new(2004, 4, 15), Topic.minimum(:last_read)
|
||||
assert_equal Date.new(2004, 4, 15), Topic.maximum(:last_read)
|
||||
assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).minimum(:last_read))
|
||||
assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).maximum(:last_read))
|
||||
end
|
||||
|
||||
def test_select_avg_with_group_by_as_virtual_attribute_with_sql
|
||||
rails_core = companies(:rails_core)
|
||||
|
||||
|
|
Loading…
Reference in a new issue