mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Always prefer class types to query types when casting group
When `group` is used in combination with any calculation method, the resulting hash uses the grouping expression as the key. Currently we're incorrectly always favoring the type reported by the query, instead of the type known by the class. This causes differing behavior depending on whether the adaptor actually gives proper types with the query or not. After this change, the behavior will be the same on all adaptors -- we see if we know the type from the class, fall back to the type from the query, and finally fall back to the identity type. Fixes #25595
This commit is contained in:
parent
79bc06647c
commit
a45363a2fb
4 changed files with 23 additions and 6 deletions
|
@ -1,3 +1,8 @@
|
|||
* Using `group` with an attribute that has a custom type will properly cast
|
||||
the hash keys after calling a calculation method like `count`. Fixes #25595.
|
||||
|
||||
*Sean Griffin*
|
||||
|
||||
* Fix the generated `#to_param` method to use `omission: ''` so that
|
||||
the resulting output is actually up to 20 characters, not
|
||||
effectively 17 to leave room for the default "...".
|
||||
|
|
|
@ -282,8 +282,12 @@ module ActiveRecord
|
|||
#
|
||||
# +attr_name+ The name of the attribute to retrieve the type for. Must be
|
||||
# a string
|
||||
def type_for_attribute(attr_name)
|
||||
attribute_types[attr_name]
|
||||
def type_for_attribute(attr_name, &block)
|
||||
if block
|
||||
attribute_types.fetch(attr_name, &block)
|
||||
else
|
||||
attribute_types[attr_name]
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a hash where the keys are column names and the values are
|
||||
|
|
|
@ -312,8 +312,10 @@ module ActiveRecord
|
|||
|
||||
Hash[calculated_data.map do |row|
|
||||
key = group_columns.map { |aliaz, col_name|
|
||||
column = calculated_data.column_types.fetch(aliaz) do
|
||||
type_for(col_name)
|
||||
column = type_for(col_name) do
|
||||
calculated_data.column_types.fetch(aliaz) do
|
||||
Type::Value.new
|
||||
end
|
||||
end
|
||||
type_cast_calculated_value(row[aliaz], column)
|
||||
}
|
||||
|
@ -346,9 +348,9 @@ module ActiveRecord
|
|||
@klass.connection.table_alias_for(table_name)
|
||||
end
|
||||
|
||||
def type_for(field)
|
||||
def type_for(field, &block)
|
||||
field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split('.').last
|
||||
@klass.type_for_attribute(field_name)
|
||||
@klass.type_for_attribute(field_name, &block)
|
||||
end
|
||||
|
||||
def type_cast_calculated_value(value, type, operation = nil)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require "cases/helper"
|
||||
require "models/book"
|
||||
require 'models/club'
|
||||
require 'models/company'
|
||||
require "models/contract"
|
||||
|
@ -793,4 +794,9 @@ class CalculationsTest < ActiveRecord::TestCase
|
|||
assert_equal 50, result[1].credit_limit
|
||||
assert_equal 50, result[2].credit_limit
|
||||
end
|
||||
|
||||
def test_group_by_attribute_with_custom_type
|
||||
Book.create!(status: :published)
|
||||
assert_equal({ "published" => 1 }, Book.group(:status).count)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue