aggregate_columns 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- aggregate_rel = klass.select( "#{foreign_key}, #{aggregate_expression} AS #{result_column}" ).from( aggregate_table_name ).group( foreign_key )
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.#{foreign_key}" ).
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 ).where( "#{table_name}.id = #{foreign_key}" )
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}" ).
@@ -1,3 +1,3 @@
1
1
  module AggregateColumns
2
- VERSION = "0.9.6"
2
+ VERSION = "0.9.7"
3
3
  end
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
- version: 0.9.6
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
- date: 2012-01-26 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
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
- requirement: &7063280 !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
17
25
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '2'
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 2
32
+ version: "2"
22
33
  type: :runtime
23
- prerelease: false
24
- version_requirements: *7063280
25
- - !ruby/object:Gem::Dependency
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
26
36
  name: rake
27
- requirement: &7061440 !ruby/object:Gem::Requirement
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
28
39
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
33
47
  type: :development
34
- prerelease: false
35
- version_requirements: *7061440
36
- - !ruby/object:Gem::Dependency
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
37
50
  name: activerecord
38
- requirement: &7055400 !ruby/object:Gem::Requirement
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
39
53
  none: false
40
- requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
43
- version: '2'
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 7
58
+ segments:
59
+ - 2
60
+ version: "2"
44
61
  type: :development
45
- prerelease: false
46
- version_requirements: *7055400
47
- - !ruby/object:Gem::Dependency
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
48
64
  name: activesupport
49
- requirement: &7052700 !ruby/object:Gem::Requirement
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
50
67
  none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '2'
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 7
72
+ segments:
73
+ - 2
74
+ version: "2"
55
75
  type: :development
56
- prerelease: false
57
- version_requirements: *7052700
58
- - !ruby/object:Gem::Dependency
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
59
78
  name: activerecord-nulldb-adapter
60
- requirement: &7051800 !ruby/object:Gem::Requirement
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
- prerelease: false
68
- version_requirements: *7051800
69
- description: ''
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
- files:
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
- homepage: ''
113
+ has_rdoc: true
114
+ homepage: ""
87
115
  licenses: []
116
+
88
117
  post_install_message:
89
118
  rdoc_options: []
90
- require_paths:
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
- version: '0'
98
- required_rubygems_version: !ruby/object:Gem::Requirement
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
- version: '0'
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.8.11
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