aggregate_columns 0.9.6 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/aggregate_columns.rb +14 -3
- data/lib/aggregate_columns/version.rb +1 -1
- data/test/rails_3_test.rb +17 -5
- metadata +99 -62
data/lib/aggregate_columns.rb
CHANGED
@@ -72,20 +72,31 @@ module AggregateColumns
|
|
72
72
|
# (and not that complicated) to make it work on ActiveRecord::Relation
|
73
73
|
# instances
|
74
74
|
assoc_reflection = reflect_on_association( association )
|
75
|
+
through_reflection = assoc_reflection.through_reflection
|
75
76
|
foreign_key = assoc_reflection.foreign_key
|
76
77
|
aggregate_table_name = assoc_reflection.table_name
|
77
78
|
klass = assoc_reflection.klass
|
78
79
|
join_type = options[:join_type] # TODO: check if within allowed values
|
79
80
|
|
80
81
|
if join_type
|
81
|
-
|
82
|
+
main_foreign_key = through_reflection ? through_reflection.foreign_key : foreign_key
|
83
|
+
aggregate_rel = klass.select( "#{main_foreign_key}, #{aggregate_expression} AS #{result_column}" ).from( aggregate_table_name ).group( main_foreign_key )
|
84
|
+
if through_reflection
|
85
|
+
aggregate_rel = aggregate_rel.joins( "INNER JOIN #{through_reflection.table_name} ON #{through_reflection.table_name}.id = #{aggregate_table_name}.#{assoc_reflection.foreign_key}" )
|
86
|
+
end
|
82
87
|
aggregate_rel = yield( aggregate_rel ) if block_given?
|
83
88
|
rel = rel.
|
84
|
-
joins( "#{join_type.to_s.upcase} JOIN (#{aggregate_rel.to_sql}) #{result_column}_join ON #{table_name}.id = #{result_column}_join.#{
|
89
|
+
joins( "#{join_type.to_s.upcase} JOIN (#{aggregate_rel.to_sql}) #{result_column}_join ON #{table_name}.id = #{result_column}_join.#{main_foreign_key}" ).
|
85
90
|
select( result_column.to_s ).
|
86
91
|
order( "#{result_column} DESC" ) # You might reorder if you want to have it differently
|
87
92
|
else
|
88
|
-
aggregate_rel = klass.select( "#{aggregate_expression} AS #{result_column}" ).from( aggregate_table_name )
|
93
|
+
aggregate_rel = klass.select( "#{aggregate_expression} AS #{result_column}" ).from( aggregate_table_name )
|
94
|
+
if through_reflection
|
95
|
+
aggregate_rel = aggregate_rel.joins( "INNER JOIN #{through_reflection.table_name} ON #{through_reflection.table_name}.id = #{aggregate_table_name}.#{assoc_reflection.foreign_key}" ).where( "#{table_name}.id = #{through_reflection.foreign_key}" )
|
96
|
+
else
|
97
|
+
aggregate_rel = aggregate_rel.where( "#{table_name}.id = #{aggregate_table_name}.#{foreign_key}" )
|
98
|
+
end
|
99
|
+
|
89
100
|
aggregate_rel = yield( aggregate_rel ) if block_given?
|
90
101
|
rel = rel.
|
91
102
|
select( "(#{aggregate_rel.to_sql}) AS #{result_column}" ).
|
data/test/rails_3_test.rb
CHANGED
@@ -16,16 +16,22 @@ if Rails::VERSION::MAJOR == 3
|
|
16
16
|
|
17
17
|
class Post < ActiveRecord::Base
|
18
18
|
has_many :comments
|
19
|
+
has_many :notes, :through => :comments
|
19
20
|
end
|
20
21
|
|
21
22
|
class Comment < ActiveRecord::Base
|
22
23
|
belongs_to :post
|
24
|
+
has_many :notes
|
25
|
+
end
|
26
|
+
|
27
|
+
class Note < ActiveRecord::Base
|
28
|
+
belongs_to :comment
|
23
29
|
end
|
24
30
|
|
25
31
|
def test_only_association
|
26
32
|
relation = Post.aggregate_columns( :association => :comments )
|
27
33
|
assert_equal 2, relation.select_values.count
|
28
|
-
assert relation.select_values.include?( "(SELECT count(*) AS comment_count FROM comments WHERE (posts.id = post_id)) AS comment_count" )
|
34
|
+
assert relation.select_values.include?( "(SELECT count(*) AS comment_count FROM comments WHERE (posts.id = comments.post_id)) AS comment_count" )
|
29
35
|
assert_equal relation.order_values, ["comment_count DESC"]
|
30
36
|
assert_empty relation.where_values
|
31
37
|
assert_empty relation.joins_values
|
@@ -39,7 +45,7 @@ if Rails::VERSION::MAJOR == 3
|
|
39
45
|
def test_function_and_column
|
40
46
|
relation = Post.aggregate_columns( :association => :comments, :function => :max, :column => :created_at )
|
41
47
|
assert_equal 2, relation.select_values.count
|
42
|
-
assert relation.select_values.include?( "(SELECT max(created_at) AS comments_created_at_max FROM comments WHERE (posts.id = post_id)) AS comments_created_at_max" )
|
48
|
+
assert relation.select_values.include?( "(SELECT max(created_at) AS comments_created_at_max FROM comments WHERE (posts.id = comments.post_id)) AS comments_created_at_max" )
|
43
49
|
assert_equal relation.order_values, ["comments_created_at_max DESC"]
|
44
50
|
assert_empty relation.where_values
|
45
51
|
assert_empty relation.joins_values
|
@@ -48,7 +54,7 @@ if Rails::VERSION::MAJOR == 3
|
|
48
54
|
def test_expression
|
49
55
|
relation = Post.aggregate_columns( :association => :comments, :expression => "(created_at + updated_at)", :result_column => :ultimate_at )
|
50
56
|
assert_equal 2, relation.select_values.count
|
51
|
-
assert relation.select_values.include?( "(SELECT (created_at + updated_at) AS ultimate_at FROM comments WHERE (posts.id = post_id)) AS ultimate_at" )
|
57
|
+
assert relation.select_values.include?( "(SELECT (created_at + updated_at) AS ultimate_at FROM comments WHERE (posts.id = comments.post_id)) AS ultimate_at" )
|
52
58
|
assert_equal relation.order_values, ["ultimate_at DESC"]
|
53
59
|
assert_empty relation.where_values
|
54
60
|
assert_empty relation.joins_values
|
@@ -57,7 +63,7 @@ if Rails::VERSION::MAJOR == 3
|
|
57
63
|
def test_result_column
|
58
64
|
relation = Post.aggregate_columns( :association => :comments, :function => :max, :column => :created_at, :result_column => :max_created_at )
|
59
65
|
assert_equal 2, relation.select_values.count
|
60
|
-
assert relation.select_values.include?( "(SELECT max(created_at) AS max_created_at FROM comments WHERE (posts.id = post_id)) AS max_created_at" )
|
66
|
+
assert relation.select_values.include?( "(SELECT max(created_at) AS max_created_at FROM comments WHERE (posts.id = comments.post_id)) AS max_created_at" )
|
61
67
|
assert_equal relation.order_values, ["max_created_at DESC"]
|
62
68
|
assert_empty relation.where_values
|
63
69
|
assert_empty relation.joins_values
|
@@ -75,7 +81,7 @@ if Rails::VERSION::MAJOR == 3
|
|
75
81
|
def test_where_clauses
|
76
82
|
relation = Post.where( :id => 2 ).aggregate_columns( :association => :comments ) { |rel| rel.where( :id => 1 ) }
|
77
83
|
assert_equal "posts.id = 2", relation.where_values.first.to_sql # Additional "where" means where_values must be processed with to_sql instead of querying directly
|
78
|
-
assert relation.select_values.include?( "(SELECT count(*) AS comment_count FROM comments WHERE comments.id = 1 AND (posts.id = post_id)) AS comment_count" )
|
84
|
+
assert relation.select_values.include?( "(SELECT count(*) AS comment_count FROM comments WHERE comments.id = 1 AND (posts.id = comments.post_id)) AS comment_count" )
|
79
85
|
end
|
80
86
|
|
81
87
|
def test_multiple_aggregates
|
@@ -85,5 +91,11 @@ if Rails::VERSION::MAJOR == 3
|
|
85
91
|
assert relation.joins_values.include?( "RIGHT JOIN (SELECT post_id, count(*) AS comment_count FROM comments GROUP BY post_id) comment_count_join ON posts.id = comment_count_join.post_id" )
|
86
92
|
end
|
87
93
|
|
94
|
+
def test_through_association
|
95
|
+
relation = Post.aggregate_columns( :association => :notes )
|
96
|
+
assert relation.select_values.include?( "(SELECT count(*) AS note_count FROM notes INNER JOIN comments ON comments.id = notes.comment_id WHERE (posts.id = post_id)) AS note_count" )
|
97
|
+
relation = Post.aggregate_columns( :association => :notes, :join_type => :right )
|
98
|
+
assert_equal relation.joins_values, ["RIGHT JOIN (SELECT post_id, count(*) AS note_count FROM notes INNER JOIN comments ON comments.id = notes.comment_id GROUP BY post_id) note_count_join ON posts.id = note_count_join.post_id"]
|
99
|
+
end
|
88
100
|
end
|
89
101
|
end
|
metadata
CHANGED
@@ -1,78 +1,105 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: aggregate_columns
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 53
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 9
|
9
|
+
- 7
|
10
|
+
version: 0.9.7
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Marek Janukowicz/Starware
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-02-02 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: activerecord
|
16
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
25
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
version: "2"
|
22
33
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
26
36
|
name: rake
|
27
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
33
47
|
type: :development
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
37
50
|
name: activerecord
|
38
|
-
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
53
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 7
|
58
|
+
segments:
|
59
|
+
- 2
|
60
|
+
version: "2"
|
44
61
|
type: :development
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
48
64
|
name: activesupport
|
49
|
-
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
67
|
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 7
|
72
|
+
segments:
|
73
|
+
- 2
|
74
|
+
version: "2"
|
55
75
|
type: :development
|
56
|
-
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
76
|
+
version_requirements: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
59
78
|
name: activerecord-nulldb-adapter
|
60
|
-
|
79
|
+
prerelease: false
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
|
-
requirements:
|
63
|
-
- - =
|
64
|
-
- !ruby/object:Gem::Version
|
82
|
+
requirements:
|
83
|
+
- - "="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 23
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
- 2
|
89
|
+
- 0
|
65
90
|
version: 0.2.0
|
66
91
|
type: :development
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
email:
|
92
|
+
version_requirements: *id005
|
93
|
+
description: ""
|
94
|
+
email:
|
71
95
|
- marek@janukowicz.net
|
72
96
|
executables: []
|
97
|
+
|
73
98
|
extensions: []
|
99
|
+
|
74
100
|
extra_rdoc_files: []
|
75
|
-
|
101
|
+
|
102
|
+
files:
|
76
103
|
- .hgignore
|
77
104
|
- Gemfile
|
78
105
|
- README
|
@@ -83,31 +110,41 @@ files:
|
|
83
110
|
- test/rails_2_test.rb
|
84
111
|
- test/rails_3_test.rb
|
85
112
|
- test/test_helper.rb
|
86
|
-
|
113
|
+
has_rdoc: true
|
114
|
+
homepage: ""
|
87
115
|
licenses: []
|
116
|
+
|
88
117
|
post_install_message:
|
89
118
|
rdoc_options: []
|
90
|
-
|
119
|
+
|
120
|
+
require_paths:
|
91
121
|
- lib
|
92
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
123
|
none: false
|
94
|
-
requirements:
|
95
|
-
- -
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
|
98
|
-
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
132
|
none: false
|
100
|
-
requirements:
|
101
|
-
- -
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
hash: 3
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
version: "0"
|
104
140
|
requirements: []
|
141
|
+
|
105
142
|
rubyforge_project:
|
106
|
-
rubygems_version: 1.
|
143
|
+
rubygems_version: 1.6.2
|
107
144
|
signing_key:
|
108
145
|
specification_version: 3
|
109
146
|
summary: Create and use aggregate columns in Rails applications
|
110
|
-
test_files:
|
147
|
+
test_files:
|
111
148
|
- test/rails_2_test.rb
|
112
149
|
- test/rails_3_test.rb
|
113
150
|
- test/test_helper.rb
|