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.
@@ -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