|
3 | 3 |
|
4 | 4 | module ActiveRecord
|
5 | 5 | module Calculations
|
6 |
| - # Count operates using three different approaches. |
| 6 | + # Count the records. |
7 | 7 | #
|
8 |
| - # * Count all: By not passing any parameters to count, it will return a count of all the rows for the model. |
9 |
| - # * Count using column: By passing a column name to count, it will return a count of all the |
10 |
| - # rows for the model with supplied column present. |
11 |
| - # * Count using options will find the row count matched by the options used. |
| 8 | + # Person.count |
| 9 | + # # => the total count of all people |
12 | 10 | #
|
13 |
| - # The third approach, count using options, accepts an option hash as the only parameter. The options are: |
| 11 | + # Person.count(:age) |
| 12 | + # # => returns the total count of all people whose age is present in database |
14 | 13 | #
|
15 |
| - # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. |
16 |
| - # See conditions in the intro to ActiveRecord::Base. |
17 |
| - # * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" |
18 |
| - # (rarely needed) or named associations in the same form used for the <tt>:include</tt> option, which will |
19 |
| - # perform an INNER JOIN on the associated table(s). If the value is a string, then the records |
20 |
| - # will be returned read-only since they will have attributes that do not correspond to the table's columns. |
21 |
| - # Pass <tt>:readonly => false</tt> to override. |
22 |
| - # * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. |
23 |
| - # The symbols named refer to already defined associations. When using named associations, count |
24 |
| - # returns the number of DISTINCT items for the model you're counting. |
25 |
| - # See eager loading under Associations. |
26 |
| - # * <tt>:order</tt>: An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations). |
27 |
| - # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. |
28 |
| - # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you, for example, |
29 |
| - # want to do a join but not include the joined columns. |
30 |
| - # * <tt>:distinct</tt>: Set this to true to make this a distinct calculation, such as |
31 |
| - # SELECT COUNT(DISTINCT posts.id) ... |
32 |
| - # * <tt>:from</tt> - By default, this is the table name of the class, but can be changed to an |
33 |
| - # alternate table name (or even the name of a database view). |
| 14 | + # Person.count(:all) |
| 15 | + # # => performs a COUNT(*) (:all is an alias for '*') |
34 | 16 | #
|
35 |
| - # Examples for counting all: |
36 |
| - # Person.count # returns the total count of all people |
37 |
| - # |
38 |
| - # Examples for counting by column: |
39 |
| - # Person.count(:age) # returns the total count of all people whose age is present in database |
40 |
| - # |
41 |
| - # Examples for count with options: |
42 |
| - # Person.count(:conditions => "age > 26") |
43 |
| - # |
44 |
| - # # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN. |
45 |
| - # Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job) |
46 |
| - # |
47 |
| - # # finds the number of rows matching the conditions and joins. |
48 |
| - # Person.count(:conditions => "age > 26 AND job.salary > 60000", |
49 |
| - # :joins => "LEFT JOIN jobs on jobs.person_id = person.id") |
50 |
| - # |
51 |
| - # Person.count('id', :conditions => "age > 26") # Performs a COUNT(id) |
52 |
| - # Person.count(:all, :conditions => "age > 26") # Performs a COUNT(*) (:all is an alias for '*') |
53 |
| - # |
54 |
| - # Note: <tt>Person.count(:all)</tt> will not work because it will use <tt>:all</tt> as the condition. |
55 |
| - # Use Person.count instead. |
| 17 | + # Person.count(:age, distinct: true) |
| 18 | + # # => counts the number of different age values |
56 | 19 | def count(column_name = nil, options = {})
|
57 | 20 | column_name, options = nil, column_name if column_name.is_a?(Hash)
|
58 | 21 | calculate(:count, column_name, options)
|
@@ -98,69 +61,48 @@ def sum(*args)
|
98 | 61 | end
|
99 | 62 |
|
100 | 63 | # This calculates aggregate values in the given column. Methods for count, sum, average,
|
101 |
| - # minimum, and maximum have been added as shortcuts. Options such as <tt>:conditions</tt>, |
102 |
| - # <tt>:order</tt>, <tt>:group</tt>, <tt>:having</tt>, and <tt>:joins</tt> can be passed to customize the query. |
| 64 | + # minimum, and maximum have been added as shortcuts. |
103 | 65 | #
|
104 | 66 | # There are two basic forms of output:
|
| 67 | + # |
105 | 68 | # * Single aggregate value: The single value is type cast to Fixnum for COUNT, Float
|
106 | 69 | # for AVG, and the given column's type for everything else.
|
107 |
| - # * Grouped values: This returns an ordered hash of the values and groups them by the |
108 |
| - # <tt>:group</tt> option. It takes either a column name, or the name of a belongs_to association. |
109 | 70 | #
|
110 |
| - # values = Person.maximum(:age, :group => 'last_name') |
| 71 | + # * Grouped values: This returns an ordered hash of the values and groups them. It |
| 72 | + # takes either a column name, or the name of a belongs_to association. |
| 73 | + # |
| 74 | + # values = Person.group('last_name').maximum(:age) |
111 | 75 | # puts values["Drake"]
|
112 | 76 | # => 43
|
113 | 77 | #
|
114 | 78 | # drake = Family.find_by_last_name('Drake')
|
115 |
| - # values = Person.maximum(:age, :group => :family) # Person belongs_to :family |
| 79 | + # values = Person.group(:family).maximum(:age) # Person belongs_to :family |
116 | 80 | # puts values[drake]
|
117 | 81 | # => 43
|
118 | 82 | #
|
119 | 83 | # values.each do |family, max_age|
|
120 | 84 | # ...
|
121 | 85 | # end
|
122 | 86 | #
|
123 |
| - # Options: |
124 |
| - # * <tt>:conditions</tt> - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. |
125 |
| - # See conditions in the intro to ActiveRecord::Base. |
126 |
| - # * <tt>:include</tt>: Eager loading, see Associations for details. Since calculations don't load anything, |
127 |
| - # the purpose of this is to access fields on joined tables in your conditions, order, or group clauses. |
128 |
| - # * <tt>:joins</tt> - An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". |
129 |
| - # (Rarely needed). |
130 |
| - # The records will be returned read-only since they will have attributes that do not correspond to the |
131 |
| - # table's columns. |
132 |
| - # * <tt>:order</tt> - An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations). |
133 |
| - # * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. |
134 |
| - # * <tt>:select</tt> - By default, this is * as in SELECT * FROM, but can be changed if you for example |
135 |
| - # want to do a join, but not include the joined columns. |
136 |
| - # * <tt>:distinct</tt> - Set this to true to make this a distinct calculation, such as |
137 |
| - # SELECT COUNT(DISTINCT posts.id) ... |
138 |
| - # |
139 | 87 | # Examples:
|
140 | 88 | # Person.calculate(:count, :all) # The same as Person.count
|
141 | 89 | # Person.average(:age) # SELECT AVG(age) FROM people...
|
142 |
| - # Person.minimum(:age, :conditions => ['last_name != ?', 'Drake']) # Selects the minimum age for |
143 |
| - # # everyone with a last name other than 'Drake' |
144 | 90 | #
|
145 | 91 | # # Selects the minimum age for any family without any minors
|
146 |
| - # Person.minimum(:age, :having => 'min(age) > 17', :group => :last_name) |
| 92 | + # Person.group(:last_name).having("min(age) > 17").minimum(:age) |
147 | 93 | #
|
148 | 94 | # Person.sum("2 * age")
|
149 | 95 | def calculate(operation, column_name, options = {})
|
150 |
| - if options.except(:distinct).present? |
151 |
| - apply_finder_options(options.except(:distinct)).calculate(operation, column_name, :distinct => options[:distinct]) |
152 |
| - else |
153 |
| - relation = with_default_scope |
154 |
| - |
155 |
| - if relation.equal?(self) |
156 |
| - if eager_loading? || (includes_values.present? && references_eager_loaded_tables?) |
157 |
| - construct_relation_for_association_calculations.calculate(operation, column_name, options) |
158 |
| - else |
159 |
| - perform_calculation(operation, column_name, options) |
160 |
| - end |
| 96 | + relation = with_default_scope |
| 97 | + |
| 98 | + if relation.equal?(self) |
| 99 | + if eager_loading? || (includes_values.present? && references_eager_loaded_tables?) |
| 100 | + construct_relation_for_association_calculations.calculate(operation, column_name, options) |
161 | 101 | else
|
162 |
| - relation.calculate(operation, column_name, options) |
| 102 | + perform_calculation(operation, column_name, options) |
163 | 103 | end
|
| 104 | + else |
| 105 | + relation.calculate(operation, column_name, options) |
164 | 106 | end
|
165 | 107 | rescue ThrowResult
|
166 | 108 | 0
|
|
0 commit comments