aggregate_columns 0.9 → 0.9.1

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/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
-