5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/aggregate_columns/methods_rails_4.rb', line 5
def aggregate_columns( options )
rel = self.select( "#{table_name}.*" )
options.assert_valid_keys( :association, :column, :function, :result_column, :join_type, :expression )
association = options[:association]
unless association
raise ArgumentError, "No association given"
end
aggregate_expression = options[:expression]
result_column = options[:result_column]
unless aggregate_expression
field = options[:column] || '*'
function = options[:function] || :count
aggregate_expression = "#{function}(#{field})"
result_column ||= field == '*' ? "#{association.to_s.singularize}_#{function}" : "#{association}_#{field}_#{function}"
end
assoc_reflection = reflect_on_association( association )
through_reflection = assoc_reflection.through_reflection
foreign_key = assoc_reflection.foreign_key
aggregate_table_name = assoc_reflection.table_name
klass = assoc_reflection.klass
join_type = options[:join_type]
join_reflection = through_reflection || assoc_reflection
join_foreign_key = join_reflection.foreign_key
aggregate_rel = klass.select( "#{aggregate_expression} AS #{result_column}" ).from( aggregate_table_name )
if through_reflection
aggregate_rel = aggregate_rel.joins( "INNER JOIN #{through_reflection.table_name} ON #{through_reflection.table_name}.id = #{aggregate_table_name}.#{assoc_reflection.foreign_key}" )
end
if assoc_reflection.scope
aggregate_rel = aggregate_rel.merge( assoc_reflection.scope )
end
if through_reflection && through_reflection.scope
aggregate_rel = aggregate_rel.merge( through_reflection.scope )
end
if join_type
aggregate_rel = aggregate_rel.select( join_foreign_key ).group( join_foreign_key )
aggregate_rel = yield( aggregate_rel ) if block_given?
rel = rel.
joins( "#{join_type.to_s.upcase} JOIN (#{aggregate_rel.to_sql}) #{result_column}_join ON #{table_name}.id = #{result_column}_join.#{join_foreign_key}" ).
select( result_column.to_s ).
order( "#{result_column} DESC NULLS LAST" ) else
aggregate_rel = aggregate_rel.where( "#{table_name}.id = #{join_reflection.quoted_table_name}.#{join_reflection.foreign_key}" )
aggregate_rel = yield( aggregate_rel ) if block_given?
rel = rel.
select( "(#{aggregate_rel.to_sql}) AS #{result_column}" ).
order( "#{result_column} DESC NULLS LAST" ) end
return rel
end
|