This project is archived and is in readonly mode.
average() returns integer values instead of decimals
-
Andreas Mayer
- Tag changed from rails 3.0.3, aggregations, arel to rails 3.0.3, activerecord, aggregations
-
Andreas Mayer
- Tag changed from rails 3.0.3, activerecord, aggregations to rails 3.0.3, activerecord, aggregations, rails3
-
2kan
It works for me in edge for postgres.
ree-1.8.7-2010.02 > Post.calculate(:average, 'rating') => #<BigDecimal:102740628,'0.125E2',18(27)> ree-1.8.7-2010.02 > -
2kan
It works for me in edge for postgres.
ree-1.8.7-2010.02 > Post.calculate(:average, 'rating') => #<BigDecimal:102740628,'0.125E2',18(27)> ree-1.8.7-2010.02 > -
Andreas Mayer
Maybe a MySQL driver-related issue? Or could this have been fixed in edge, shall I try?
-
Tiago Fernandes
Think this bug is related with the type cast of the calculated value. the activerecord tries to cast the value based on the type of the column.
If the rating column is of type integer it should calculate integer/integer = integer. If raging is of type float, it calculates float/integer = float.
What is the type of your rating column ?
-
Tiago Fernandes
Did a quick test with a fresh rails install and sqlite3, and the calculated value is different for columns of type integer and float.
-
Andreas Mayer
My :ratings are integer. Maybe this is the problem because the avg() of integer values still can be float - the avg() of 1 and 2 is not 1 but 1.5
-
Jarrett Meyer
In ticket 6158 ( #6158 #count on decimal column returns BigDecimal ), performing a COUNT() operation on a decimal column is returning a decimal, event though a count should always be a whole integer. I've already added a unit test and patch for that particular patch. I suppose this is the inverse of that issue.
There's a method in /lib/active_record/relation/calculations.rb that coerces the type returned to be the same as the column type.
-
Tiago Fernandes
Think that the bug is related with type_cast method in the schema_definitions.rb
If you create a second field rating2 of type float, and test Post.average(:rating) vs Post.average(:rating2), you will notice that the value class in on both Float, but the class of type is integer and float respectively.
From the comment in the code i think that value is supposed to be String, but as you can test, it can be also a float. A small fix can be: "return value if !value.is_a?(String)" in the beginning of the type_cast method.
Casts value (which is a String) to an appropriate instance.
def type_cast(value)
{mkd-extraction-02893f2974f2d821de0529f9bcc610de}
return nil if value.nil? puts "Class: #{type.class}" puts "Type: #{type}" puts "Value class: #{value.class}" puts "Value: #{value}" case typeend end
-
Tiago Fernandes
# Casts value (which is a String) to an appropriate instance. def type_cast(value) return nil if value.nil? puts "Class: #{type.class}" puts "Type: #{type}" puts "Value class: #{value.class}" puts "Value: #{value}" case type when :string then value when :text then value when :integer then value.to_i rescue value ? 1 : 0 when :float then value.to_f when :decimal then self.class.value_to_decimal(value) when :datetime then self.class.string_to_time(value) when :timestamp then self.class.string_to_time(value) when :time then self.class.string_to_dummy_time(value) when :date then self.class.string_to_date(value) when :binary then self.class.binary_to_string(value) when :boolean then self.class.value_to_boolean(value) else value end end -
Janis Vitums
This bug comes form commit - we should always cast the value based on the column October 11, 2010 when calculations type casts was changed.
in module Calculations method:
def type_cast_calculated_value(value, column, operation = nil) if value.is_a?(String) || value.nil? case operation when 'count' then value.to_i when 'sum' then type_cast_using_column(value || '0', column) when 'average' then value.try(:to_d) else type_cast_using_column(value, column) end else value end endwas changed to:
def type_cast_calculated_value(value, column, operation = nil)
if value.is_a?(String) || value.nil? case operation when 'count' then value.to_i when 'sum' then type_cast_using_column(value || '0', column) when 'average' then value.try(:to_d) else type_cast_using_column(value, column) end else type_cast_using_column(value, column) end endnew method is not working any more as described in documentation for Calculate method (AVG should return Float)
-
Raimonds Simanovskis
I created pull request with fix for this issue
-
Josh Kalderimis
- Assigned user set to Santiago Pastorino
This issue can be closed as it is already in master
-
Santiago Pastorino
- State changed from new to resolved
- Importance changed from to Low