Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 274 lines (245 sloc) 14.274 kb
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
1 module ActiveRecord
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
2 module Calculations #:nodoc:
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
3 CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct, :limit, :offset, :include]
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
4 def self.included(base)
5 base.extend(ClassMethods)
6 end
7
8 module ClassMethods
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
9 # Count operates using three different approaches.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
10 #
11 # * Count all: By not passing any parameters to count, it will return a count of all the rows for the model.
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
12 # * Count using column : By passing a column name to count, it will return a count of all the rows for the model with supplied column present
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
13 # * Count using options will find the row count matched by the options used.
14 #
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
15 # The third approach, count using options, accepts an option hash as the only parameter. The options are:
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
16 #
17 # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
9661395 Remove references to nonexistent :joins documentation. Closes #10498 [tp...
Marcel Molina authored
18 # * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed)
19 # or named associations in the same form used for the :include option, which will perform an INNER JOIN on the associated table(s).
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
20 # If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table's columns.
21 # Pass :readonly => false to override.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
22 # * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
23 # to already defined associations. When using named associations, count returns the number of DISTINCT items for the model you're counting.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
24 # See eager loading under Associations.
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
25 # * <tt>:order</tt>: An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations).
26 # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
27 # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you, for example, want to do a join but not
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
28 # include the joined columns.
29 # * <tt>:distinct</tt>: Set this to true to make this a distinct calculation, such as SELECT COUNT(DISTINCT posts.id) ...
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
30 #
31 # Examples for counting all:
32 # Person.count # returns the total count of all people
33 #
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
34 # Examples for counting by column:
35 # Person.count(:age) # returns the total count of all people whose age is present in database
36 #
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
37 # Examples for count with options:
38 # Person.count(:conditions => "age > 26")
39 # Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job) # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN.
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
40 # Person.count(:conditions => "age > 26 AND job.salary > 60000", :joins => "LEFT JOIN jobs on jobs.person_id = person.id") # finds the number of rows matching the conditions and joins.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
41 # Person.count('id', :conditions => "age > 26") # Performs a COUNT(id)
42 # Person.count(:all, :conditions => "age > 26") # Performs a COUNT(*) (:all is an alias for '*')
43 #
44 # Note: Person.count(:all) will not work because it will use :all as the condition. Use Person.count instead.
45 def count(*args)
872c5f4 risk danger olson Remove deprecated count(conditions=nil, joins=nil) usage. Closes #8993 ...
technoweenie authored
46 calculate(:count, *construct_count_options_from_args(*args))
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
47 end
48
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
49 # Calculates the average value on a given column. The value is returned as a float. See #calculate for examples with options.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
50 #
51 # Person.average('age')
52 def average(column_name, options = {})
53 calculate(:avg, column_name, options)
54 end
55
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
56 # Calculates the minimum value on a given column. The value is returned with the same data type of the column. See #calculate for examples with options.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
57 #
58 # Person.minimum('age')
59 def minimum(column_name, options = {})
60 calculate(:min, column_name, options)
61 end
62
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
63 # Calculates the maximum value on a given column. The value is returned with the same data type of the column. See #calculate for examples with options.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
64 #
65 # Person.maximum('age')
66 def maximum(column_name, options = {})
67 calculate(:max, column_name, options)
68 end
69
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
70 # Calculates the sum of values on a given column. The value is returned with the same data type of the column. See #calculate for examples with options.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
71 #
456ddc6 David Heinemeier Hansson Doc fix (closes #4014) [thijs@fngtps.com]
dhh authored
72 # Person.sum('age')
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
73 def sum(column_name, options = {})
78c2d9f risk danger olson ActiveRecord::Base#sum defaults to 0 if no rows are returned. Closes #1...
technoweenie authored
74 calculate(:sum, column_name, options) || 0
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
75 end
76
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
77 # This calculates aggregate values in the given column. Methods for count, sum, average, minimum, and maximum have been added as shortcuts.
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
78 # Options such as :conditions, :order, :group, :having, and :joins can be passed to customize the query.
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
79 #
80 # There are two basic forms of output:
81 # * Single aggregate value: The single value is type cast to Fixnum for COUNT, Float for AVG, and the given column's type for everything else.
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
82 # * Grouped values: This returns an ordered hash of the values and groups them by the :group option. It takes either a column name, or the name
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
83 # of a belongs_to association.
84 #
85 # values = Person.maximum(:age, :group => 'last_name')
86 # puts values["Drake"]
87 # => 43
88 #
89 # drake = Family.find_by_last_name('Drake')
90 # values = Person.maximum(:age, :group => :family) # Person belongs_to :family
91 # puts values[drake]
92 # => 43
93 #
94 # values.each do |family, max_age|
95 # ...
96 # end
97 #
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
98 # Options:
9450262 Standardize on using hyphens rather than colons to separate option names...
Marcel Molina authored
99 # * <tt>:conditions</tt> - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
ee6b607 Document how the :include option can be used in Calculations::calculate....
Marcel Molina authored
100 # * <tt>:include</tt>: Eager loading, see Associations for details. Since calculations don't load anything, the purpose of this is to access fields on joined tables in your conditions, order, or group clauses.
9450262 Standardize on using hyphens rather than colons to separate option names...
Marcel Molina authored
101 # * <tt>:joins</tt> - An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed).
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
102 # The records will be returned read-only since they will have attributes that do not correspond to the table's columns.
9450262 Standardize on using hyphens rather than colons to separate option names...
Marcel Molina authored
103 # * <tt>:order</tt> - An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations).
104 # * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.
105 # * <tt>:select</tt> - By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
106 # include the joined columns.
9450262 Standardize on using hyphens rather than colons to separate option names...
Marcel Molina authored
107 # * <tt>:distinct</tt> - Set this to true to make this a distinct calculation, such as SELECT COUNT(DISTINCT posts.id) ...
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
108 #
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
109 # Examples:
110 # Person.calculate(:count, :all) # The same as Person.count
111 # Person.average(:age) # SELECT AVG(age) FROM people...
112 # Person.minimum(:age, :conditions => ['last_name != ?', 'Drake']) # Selects the minimum age for everyone with a last name other than 'Drake'
113 # Person.minimum(:age, :having => 'min(age) > 17', :group => :last_name) # Selects the minimum age for any family without any minors
9e45586 David Heinemeier Hansson Ensure that you can still do expressions in calculations (closes #11355)...
dhh authored
114 # Person.sum("2 * age")
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
115 def calculate(operation, column_name, options = {})
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
116 validate_calculation_options(operation, options)
117 column_name = options[:select] if options[:select]
ad9f678 David Heinemeier Hansson Compatibility patches for calculations
dhh authored
118 column_name = '*' if column_name == :all
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
119 column = column_for column_name
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
120 catch :invalid_query do
121 if options[:group]
122 return execute_grouped_calculation(operation, column_name, column, options)
123 else
124 return execute_simple_calculation(operation, column_name, column, options)
125 end
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
126 end
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
127 0
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
128 end
129
130 protected
872c5f4 risk danger olson Remove deprecated count(conditions=nil, joins=nil) usage. Closes #8993 ...
technoweenie authored
131 def construct_count_options_from_args(*args)
df7b746 risk danger olson Fix the HasManyAssociation#count method so it uses the new ActiveRecord:...
technoweenie authored
132 options = {}
133 column_name = :all
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
134
a0bf019 Jeremy Kemper Deprecation: count class method should be called with an options hash ra...
jeremy authored
135 # We need to handle
136 # count()
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
137 # count(:column_name=:all)
a0bf019 Jeremy Kemper Deprecation: count class method should be called with an options hash ra...
jeremy authored
138 # count(options={})
139 # count(column_name=:all, options={})
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
140 case args.size
141 when 1
142 args[0].is_a?(Hash) ? options = args[0] : column_name = args[0]
143 when 2
872c5f4 risk danger olson Remove deprecated count(conditions=nil, joins=nil) usage. Closes #8993 ...
technoweenie authored
144 column_name, options = args
145 else
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
146 raise ArgumentError, "Unexpected parameters passed to count(): #{args.inspect}"
872c5f4 risk danger olson Remove deprecated count(conditions=nil, joins=nil) usage. Closes #8993 ...
technoweenie authored
147 end if args.size > 0
a413056 risk danger olson Fix and properly document/test count(column_name) usage. Closes #8999 [l...
technoweenie authored
148
df7b746 risk danger olson Fix the HasManyAssociation#count method so it uses the new ActiveRecord:...
technoweenie authored
149 [column_name, options]
150 end
a0bf019 Jeremy Kemper Deprecation: count class method should be called with an options hash ra...
jeremy authored
151
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
152 def construct_calculation_sql(operation, column_name, options) #:nodoc:
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
153 operation = operation.to_s.downcase
154 options = options.symbolize_keys
155
37adea6 David Heinemeier Hansson Address shortcomings of changeset [8054] [protocool]
dhh authored
156 scope = scope(:find)
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
157 merged_includes = merge_includes(scope ? scope[:include] : [], options[:include])
158 aggregate_alias = column_alias_for(operation, column_name)
9e45586 David Heinemeier Hansson Ensure that you can still do expressions in calculations (closes #11355)...
dhh authored
159 column_name = "#{connection.quote_table_name(table_name)}.#{column_name}" if column_names.include?(column_name.to_s)
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
160
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
161 if operation == 'count'
162 if merged_includes.any?
163 options[:distinct] = true
8f74527 Michael Koziarski Escape table names during calculation queries. [wesley.moxam, Koz] Close...
NZKoz authored
164 column_name = options[:select] || [connection.quote_table_name(table_name), primary_key] * '.'
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
165 end
166
167 if options[:distinct]
168 use_workaround = !connection.supports_count_distinct?
169 end
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
170 end
171
50538fb Michael Koziarski Don't double include DISTINCT when the user has already specified it. C...
NZKoz authored
172 if options[:distinct] && column_name.to_s !~ /\s*DISTINCT\s+/i
173 distinct = 'DISTINCT '
174 end
175 sql = "SELECT #{operation}(#{distinct}#{column_name}) AS #{aggregate_alias}"
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
176
177 # A (slower) workaround if we're using a backend, like sqlite, that doesn't support COUNT DISTINCT.
178 sql = "SELECT COUNT(*) AS #{aggregate_alias}" if use_workaround
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
179
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
180 sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
55622e0 Frederick Cheung Avoid adding two DISTINCT statements to queries in sqlite 2.
fcheung authored
181 sql << " FROM (SELECT #{distinct}#{column_name}" if use_workaround
8f74527 Michael Koziarski Escape table names during calculation queries. [wesley.moxam, Koz] Close...
NZKoz authored
182 sql << " FROM #{connection.quote_table_name(table_name)} "
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
183 if merged_includes.any?
37adea6 David Heinemeier Hansson Address shortcomings of changeset [8054] [protocool]
dhh authored
184 join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, merged_includes, options[:joins])
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
185 sql << join_dependency.join_associations.collect{|join| join.association_join }.join
186 end
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
187 add_joins!(sql, options, scope)
188 add_conditions!(sql, options[:conditions], scope)
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
189 add_limited_ids_condition!(sql, options, join_dependency) if join_dependency && !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit])
0dc53a8 When grouping, use the appropriate option key. [Marcel Molina Jr.]
Marcel Molina authored
190
191 if options[:group]
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
192 group_key = connection.adapter_name == 'FrontBase' ? :group_alias : :group_field
0dc53a8 When grouping, use the appropriate option key. [Marcel Molina Jr.]
Marcel Molina authored
193 sql << " GROUP BY #{options[group_key]} "
194 end
b2c0ddf Add support for FrontBase (http://www.frontbase.com/) with a new adapter...
Marcel Molina authored
195
196 if options[:group] && options[:having]
197 # FrontBase requires identifiers in the HAVING clause and chokes on function calls
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
198 if connection.adapter_name == 'FrontBase'
b2c0ddf Add support for FrontBase (http://www.frontbase.com/) with a new adapter...
Marcel Molina authored
199 options[:having].downcase!
200 options[:having].gsub!(/#{operation}\s*\(\s*#{column_name}\s*\)/, aggregate_alias)
201 end
b6171e7 Jeremy Kemper SQLite: count(distinct) queries supported in >= 3.2.6, fix calculations ...
jeremy authored
202
b2c0ddf Add support for FrontBase (http://www.frontbase.com/) with a new adapter...
Marcel Molina authored
203 sql << " HAVING #{options[:having]} "
204 end
205
f106e2c risk danger olson Fix bug where calculations with long alias names return null. [Rick]
technoweenie authored
206 sql << " ORDER BY #{options[:order]} " if options[:order]
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
207 add_limit!(sql, options, scope)
208 sql << ')' if use_workaround
9466211 risk danger olson fix calculations for the Oracle Adapter (closes #4626) [Michael Schoen]
technoweenie authored
209 sql
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
210 end
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
211
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
212 def execute_simple_calculation(operation, column_name, column, options) #:nodoc:
213 value = connection.select_value(construct_calculation_sql(operation, column_name, options))
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
214 type_cast_calculated_value(value, column, operation)
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
215 end
216
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
217 def execute_grouped_calculation(operation, column_name, column, options) #:nodoc:
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
218 group_attr = options[:group].to_s
219 association = reflect_on_association(group_attr.to_sym)
220 associated = association && association.macro == :belongs_to # only count belongs_to associations
5bbc461 Jeremy Kemper Fix calculations on associations with custom :foreign_key. Closes #8117 ...
jeremy authored
221 group_field = associated ? association.primary_key_name : group_attr
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
222 group_alias = column_alias_for(group_field)
223 group_column = column_for group_field
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
224 sql = construct_calculation_sql(operation, column_name, options.merge(:group_field => group_field, :group_alias => group_alias))
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
225 calculated_data = connection.select_all(sql)
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
226 aggregate_alias = column_alias_for(operation, column_name)
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
227
228 if association
229 key_ids = calculated_data.collect { |row| row[group_alias] }
230 key_records = association.klass.base_class.find(key_ids)
231 key_records = key_records.inject({}) { |hsh, r| hsh.merge(r.id => r) }
232 end
233
325cb12 risk danger olson Namespaced OrderedHash so the Rails implementation does not clash with a...
technoweenie authored
234 calculated_data.inject(ActiveSupport::OrderedHash.new) do |all, row|
b05fc40 Jeremy Kemper Calculations support non-numeric foreign keys. Closes #8154.
jeremy authored
235 key = type_cast_calculated_value(row[group_alias], group_column)
236 key = key_records[key] if associated
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
237 value = row[aggregate_alias]
57c613a Jeremy Kemper Ruby 1.9 compat: calculations don't assume array implementation of order...
jeremy authored
238 all[key] = type_cast_calculated_value(value, column, operation)
239 all
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
240 end
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
241 end
242
243 private
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
244 def validate_calculation_options(operation, options = {})
4251662 risk danger olson Allow all calculations to take the :include option, not just COUNT (clos...
technoweenie authored
245 options.assert_valid_keys(CALCULATIONS_OPTIONS)
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
246 end
ad9f678 David Heinemeier Hansson Compatibility patches for calculations
dhh authored
247
2a30594 risk danger olson documentation project patches, closes #7342, #7319, #7316, #7190 [jeremy...
technoweenie authored
248 # Converts a given key to the value that the database adapter returns as
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
249 # a usable column name.
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
250 # users.id #=> users_id
251 # sum(id) #=> sum_id
252 # count(distinct users.id) #=> count_distinct_users_id
253 # count(*) #=> count_all
254 def column_alias_for(*keys)
f106e2c risk danger olson Fix bug where calculations with long alias names return null. [Rick]
technoweenie authored
255 connection.table_alias_for(keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_'))
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
256 end
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
257
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
258 def column_for(field)
259 field_name = field.to_s.split('.').last
260 columns.detect { |c| c.name.to_s == field_name }
261 end
a8d085a David Heinemeier Hansson Make calculations typecasty! (closes #4016) [Rick Olson]
dhh authored
262
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
263 def type_cast_calculated_value(value, column, operation = nil)
264 operation = operation.to_s.downcase
265 case operation
266 when 'count' then value.to_i
1f80296 Jeremy Kemper Calculations: return nil average instead of 0 when there are no rows to ...
jeremy authored
267 when 'avg' then value && value.to_f
fed7d33 David Heinemeier Hansson Fixed documentation
dhh authored
268 else column ? column.type_cast(value) : value
269 end
99307b9 David Heinemeier Hansson Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Ba...
dhh authored
270 end
271 end
272 end
445cb5c Michael Koziarski Add support for :include to with_scope [andrew@redlinesoftware.com]
NZKoz authored
273 end
Something went wrong with that request. Please try again.