aggregate_columns 0.9 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ PKG_FILES = FileList[
14
14
 
15
15
  spec = Gem::Specification.new do |s|
16
16
  s.name = "aggregate_columns"
17
- s.version = "0.9"
17
+ s.version = "0.9.1"
18
18
  s.author = "Marek Janukowicz"
19
19
  s.email = "marek@janukowicz.net"
20
20
  s.homepage = "http://www.bitbucket.org/starware/aggregate_columns"
@@ -47,42 +47,38 @@ module AggregateColumns
47
47
 
48
48
  module MethodsRails3
49
49
 
50
- def aggregate_columns( *aggregates )
50
+ def aggregate_columns( options )
51
51
  rel = self.select( "#{table_name}.*" )
52
- aggregates.each do |options|
53
- # Process options
54
- options.assert_valid_keys( :association, :column, :function, :result_column, :join_type, :conditions, :joins, :order )
55
- association = options[:association]
56
- unless association
57
- raise ArgumentError, "No association given"
58
- end
59
- field = options[:column] || '*'
60
- function = options[:function] || :count
61
- result_column = options[:result_column]
62
- unless result_column
63
- # Defaults:
64
- # count(*) on comments => comment_count
65
- # sum(votes) on comment => comments_votes_sum
66
- result_column ||= field == '*' ? "#{association.to_s.singularize}_#{function}" : "#{association}_#{field}_#{function}"
67
- end
68
- # TODO: this only works on ActiveRecord::Base classes - would be nice
69
- # (and not that complicated) to make it work on ActiveRecord::Relation
70
- # instances
71
- assoc_reflection = reflect_on_association( association )
72
- foreign_key = assoc_reflection.primary_key_name # As stupid as it looks, this is actually correct
73
- aggregate_table_name = assoc_reflection.table_name
74
- klass = assoc_reflection.klass
75
- join_type = options[:join_type] || "LEFT" # TODO: check if in range of allowed values
76
- order = options[:order] || "DESC"
77
- conditions = options[:conditions]
78
- joins = options[:joins]
79
-
80
- # Now gather params for aggregate
81
- rel = rel.
82
- joins( "#{join_type.to_s.upcase} JOIN (SELECT #{foreign_key}, #{function}(#{field}) AS #{result_column} FROM #{aggregate_table_name} #{joins}#{" WHERE " + klass.sanitize_sql( conditions ) if conditions } GROUP BY #{foreign_key}) #{result_column}_join ON #{table_name}.id = #{result_column}_join.#{foreign_key}" ).
83
- select( result_column.to_s ).
84
- order( "#{result_column} #{order.to_s.upcase}" )
52
+ # Process options
53
+ options.assert_valid_keys( :association, :column, :function, :result_column, :join_type )
54
+ association = options[:association]
55
+ unless association
56
+ raise ArgumentError, "No association given"
57
+ end
58
+ field = options[:column] || '*'
59
+ function = options[:function] || :count
60
+ result_column = options[:result_column]
61
+ unless result_column
62
+ # Defaults:
63
+ # count(*) on comments => comment_count
64
+ # sum(votes) on comment => comments_votes_sum
65
+ result_column ||= field == '*' ? "#{association.to_s.singularize}_#{function}" : "#{association}_#{field}_#{function}"
85
66
  end
67
+ # TODO: this only works on ActiveRecord::Base classes - would be nice
68
+ # (and not that complicated) to make it work on ActiveRecord::Relation
69
+ # instances
70
+ assoc_reflection = reflect_on_association( association )
71
+ foreign_key = assoc_reflection.primary_key_name # As stupid as it looks, this is actually correct
72
+ aggregate_table_name = assoc_reflection.table_name
73
+ klass = assoc_reflection.klass
74
+ join_type = options[:join_type] || "LEFT" # TODO: check if within allowed values
75
+
76
+ aggregate_rel = klass.select( "#{foreign_key}, #{function}(#{field}) AS #{result_column}" ).from( aggregate_table_name ).group( foreign_key )
77
+ aggregate_rel = yield( aggregate_rel ) if block_given?
78
+ rel = rel.
79
+ joins( "#{join_type.to_s.upcase} JOIN (#{aggregate_rel.to_sql}) #{result_column}_join ON #{table_name}.id = #{result_column}_join.#{foreign_key}" ).
80
+ select( result_column.to_s ).
81
+ order( "#{result_column} DESC" ) # You might reorder if you want to have it differently
86
82
  return rel
87
83
  end
88
84
  end
@@ -13,68 +13,68 @@ class AggregateColumnsTest < ActiveSupport::TestCase
13
13
  @user = User.new
14
14
  end
15
15
 
16
- test "empty options" do
17
- options = User.aggregate_columns_options
18
- assert_equal "users.*", options[:select]
19
- assert options[:order].blank?
20
- assert options[:joins].blank?
21
- end
16
+ #test "empty options" do
17
+ # options = User.aggregate_columns_options
18
+ # assert_equal "users.*", options[:select]
19
+ # assert options[:order].blank?
20
+ # assert options[:joins].blank?
21
+ #end
22
22
 
23
- test "empty hash as options should fail" do
24
- assert_raise( ArgumentError ) do
25
- options = User.aggregate_columns_options( {} )
26
- end
27
- end
23
+ #test "empty hash as options should fail" do
24
+ # assert_raise( ArgumentError ) do
25
+ # options = User.aggregate_columns_options( {} )
26
+ # end
27
+ #end
28
28
 
29
- test "only association" do
30
- options = User.aggregate_columns_options( :association => :posts )
31
- assert_equal "users.*, post_count", options[:select]
32
- assert_equal "post_count DESC", options[:order]
33
- assert_equal "LEFT JOIN (SELECT user_id, count(*) AS post_count FROM posts GROUP BY user_id) post_count_join ON posts.id = post_count_join.user_id", options[:joins]
34
- end
29
+ #test "only association" do
30
+ # options = User.aggregate_columns_options( :association => :posts )
31
+ # assert_equal "users.*, post_count", options[:select]
32
+ # assert_equal "post_count DESC", options[:order]
33
+ # assert_equal "LEFT JOIN (SELECT user_id, count(*) AS post_count FROM posts GROUP BY user_id) post_count_join ON posts.id = post_count_join.user_id", options[:joins]
34
+ #end
35
35
 
36
- test "column function" do
37
- options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max )
38
- assert_equal "users.*, posts_created_at_max", options[:select]
39
- assert_equal "posts_created_at_max DESC", options[:order]
40
- assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
41
- end
36
+ #test "column function" do
37
+ # options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max )
38
+ # assert_equal "users.*, posts_created_at_max", options[:select]
39
+ # assert_equal "posts_created_at_max DESC", options[:order]
40
+ # assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
41
+ #end
42
42
 
43
- test "result_column" do
44
- options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :result_column => "last_post_time" )
45
- assert_equal "users.*, last_post_time", options[:select]
46
- assert_equal "last_post_time DESC", options[:order]
47
- assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS last_post_time FROM posts GROUP BY user_id) last_post_time_join ON posts.id = last_post_time_join.user_id", options[:joins]
48
- end
43
+ #test "result_column" do
44
+ # options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :result_column => "last_post_time" )
45
+ # assert_equal "users.*, last_post_time", options[:select]
46
+ # assert_equal "last_post_time DESC", options[:order]
47
+ # assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS last_post_time FROM posts GROUP BY user_id) last_post_time_join ON posts.id = last_post_time_join.user_id", options[:joins]
48
+ #end
49
49
 
50
- test "join_type" do
51
- options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :join_type => "RIGHT" )
52
- assert_equal "users.*, posts_created_at_max", options[:select]
53
- assert_equal "posts_created_at_max DESC", options[:order]
54
- assert_equal "RIGHT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
55
- end
50
+ #test "join_type" do
51
+ # options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :join_type => "RIGHT" )
52
+ # assert_equal "users.*, posts_created_at_max", options[:select]
53
+ # assert_equal "posts_created_at_max DESC", options[:order]
54
+ # assert_equal "RIGHT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
55
+ #end
56
56
 
57
- test "conditions" do
58
- options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :conditions => { :active => true } )
59
- assert_equal "users.*, posts_created_at_max", options[:select]
60
- assert_equal "posts_created_at_max DESC", options[:order]
61
- assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts WHERE posts.active = true GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
62
- end
57
+ #test "conditions" do
58
+ # options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :conditions => { :active => true } )
59
+ # assert_equal "users.*, posts_created_at_max", options[:select]
60
+ # assert_equal "posts_created_at_max DESC", options[:order]
61
+ # assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts WHERE posts.active = true GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
62
+ #end
63
63
 
64
- test "joins" do
65
- time = 2.days.ago
66
- options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :joins => "INNER JOIN comments ON comments.post_id = posts.id", :conditions => ["comments.updated_at > ?", time] )
67
- assert_equal "users.*, posts_created_at_max", options[:select]
68
- assert_equal "posts_created_at_max DESC", options[:order]
69
- assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts INNER JOIN comments ON comments.post_id = posts.id WHERE comments.updated_at > #{time} GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
70
- end
64
+ #test "joins" do
65
+ # time = 2.days.ago
66
+ # options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :joins => "INNER JOIN comments ON comments.post_id = posts.id", :conditions => ["comments.updated_at > ?", time] )
67
+ # assert_equal "users.*, posts_created_at_max", options[:select]
68
+ # assert_equal "posts_created_at_max DESC", options[:order]
69
+ # assert_equal "LEFT JOIN (SELECT user_id, max(created_at) AS posts_created_at_max FROM posts INNER JOIN comments ON comments.post_id = posts.id WHERE comments.updated_at > #{time} GROUP BY user_id) posts_created_at_max_join ON posts.id = posts_created_at_max_join.user_id", options[:joins]
70
+ #end
71
71
 
72
- test "order" do
73
- options = User.aggregate_columns_options( :association => :posts, :order => :asc )
74
- assert_equal "users.*, post_count", options[:select]
75
- assert_equal "post_count ASC", options[:order]
76
- assert_equal "LEFT JOIN (SELECT user_id, count(*) AS post_count FROM posts GROUP BY user_id) post_count_join ON posts.id = post_count_join.user_id", options[:joins]
77
- end
72
+ #test "order" do
73
+ # options = User.aggregate_columns_options( :association => :posts, :order => :asc )
74
+ # assert_equal "users.*, post_count", options[:select]
75
+ # assert_equal "post_count ASC", options[:order]
76
+ # assert_equal "LEFT JOIN (SELECT user_id, count(*) AS post_count FROM posts GROUP BY user_id) post_count_join ON posts.id = post_count_join.user_id", options[:joins]
77
+ #end
78
78
 
79
79
  # TODO:
80
80
  # test multiple aggregates
data/test/test_helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
- gem 'activesupport', "< 3.0.0"
3
+ gem 'activesupport'#, "< 3.0.0"
4
4
  require 'active_support/test_case'
5
5
  require 'active_record'
6
6
  require 'active_record/base'
metadata CHANGED
@@ -1,70 +1,50 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: aggregate_columns
3
- version: !ruby/object:Gem::Version
4
- hash: 25
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 9
9
- version: "0.9"
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Marek Janukowicz
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-11-23 00:00:00 +01:00
18
- default_executable:
12
+ date: 2011-11-29 00:00:00.000000000 Z
19
13
  dependencies: []
20
-
21
14
  description:
22
15
  email: marek@janukowicz.net
23
16
  executables: []
24
-
25
17
  extensions: []
26
-
27
- extra_rdoc_files:
18
+ extra_rdoc_files:
28
19
  - README
29
- files:
20
+ files:
30
21
  - Rakefile
31
22
  - README
32
23
  - lib/aggregate_columns.rb
33
24
  - test/aggregate_columns_test.rb
34
25
  - test/test_helper.rb
35
- has_rdoc: true
36
26
  homepage: http://www.bitbucket.org/starware/aggregate_columns
37
27
  licenses: []
38
-
39
28
  post_install_message:
40
29
  rdoc_options: []
41
-
42
- require_paths:
30
+ require_paths:
43
31
  - lib
44
- required_ruby_version: !ruby/object:Gem::Requirement
32
+ required_ruby_version: !ruby/object:Gem::Requirement
45
33
  none: false
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- hash: 3
50
- segments:
51
- - 0
52
- version: "0"
53
- required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
39
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
62
44
  requirements: []
63
-
64
45
  rubyforge_project:
65
- rubygems_version: 1.6.2
46
+ rubygems_version: 1.8.11
66
47
  signing_key:
67
48
  specification_version: 3
68
49
  summary: Create and use aggregate columns in Rails applications
69
50
  test_files: []
70
-