aggregate_columns 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
data/.hgignore CHANGED
@@ -1,3 +1,4 @@
1
1
  syntax: glob
2
2
  *swp
3
3
  pkg/*
4
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in aggregate_columns.gemspec
4
+ gemspec
data/README CHANGED
@@ -11,7 +11,6 @@ Take a classic example:
11
11
 
12
12
  class Post
13
13
  has_many :comments
14
- has_many :tags
15
14
  end
16
15
 
17
16
  Now let's say you want to display a table with some posts' attributes including
@@ -20,25 +19,109 @@ generates separate query for each post. Alternatively you could use counter
20
19
  cache, but it can get out of sync plus it only works on this simple example,
21
20
  while you could also need the time of latest comment for each post.
22
21
 
22
+ Rails 3
23
+ =======
23
24
 
24
25
  AggregateColumns solution would look like this:
25
26
 
26
- Post.all( Post.aggregate_columns_options( :association => :comments ))
27
+ posts = Post.aggregate_columns( :association => :comments )
28
+
29
+ SELECT posts.*, (SELECT count(*) AS comment_count FROM comments
30
+ WHERE (posts.id = post_id)) AS comment_count FROM "posts"
31
+ ORDER BY comment_count DESC
32
+
33
+ posts.first.comment_count # => "1"
34
+
35
+ This returns a full blown ActiveRecord::Relation object encapsulating a query
36
+ for posts with additional column called "comment_count" containing (big surprise
37
+ here) number of comments for each post. I'm taking advantage of the fact columns
38
+ specified in :select option are kept inside model objects (but not
39
+ type-casted, so comment_count would be a String).
27
40
 
28
- This returns posts with additional column called "comment_count" containing (big
29
- surprise here) number of comments for each post. I'm taking advantage of the
30
- fact columns specified in :select option are reachable from fetched objects (but
31
- not type-casted, so comment_count will be a String).
41
+ Options:
42
+ * :association - association to aggregate
43
+ * :function - SQL aggregate function to use, defaults to count
44
+ * :column - associated table column to aggregate, defaults to '*' (useful for
45
+ count)
46
+ * :result_column - name of resulting column, defaults to
47
+ association_field_function with exception of '*' column, which results in
48
+ association.singularize_function
49
+ * :join_type - JOIN type for in-join mode, explained later
32
50
 
51
+ Ordering defaults to aggregate column descending, you may always change it using
52
+ reorder. The reason for using this default is that in my experience this is the
53
+ only order I needed :)
33
54
 
34
55
  What if you did not want such a simple aggregation, but the one I already
35
56
  mentioned: time of latest comment for each post:
36
57
 
37
- Post.all( Post.aggregate_columns_options( :association => :comments, :function => :max, :column => :created_at ))
58
+ Post.aggregate_columns( :association => :comments, :function => :max, :column => :created_at )
59
+
60
+ SELECT posts.*, (SELECT max(created_at) AS comments_created_at_max FROM
61
+ comments WHERE (posts.id = post_id)) AS comments_created_at_max FROM "posts"
62
+ ORDER BY comments_created_at_max DESC
38
63
 
39
64
  The name of aggregated column would be comments_created_at_max in this case, but
40
65
  it can be changed using :result_column option.
41
66
 
67
+ You may add some additional relations to the subquery using a block, eg.
68
+
69
+ Post.aggregate_columns( :association => :comments ) { |rel| rel.where( :user_id => 1 ) }
70
+
71
+ SELECT posts.*, (SELECT count(*) AS comment_count FROM comments WHERE
72
+ "comments"."user_id" = 1 AND (posts.id = post_id)) AS comment_count FROM
73
+ "posts" ORDER BY comment_count DESC
74
+
75
+ This may you can limit which comments are considered for aggregation.
76
+
77
+ The only option not mentioned yet is :join_type, which can only be explained
78
+ after digging deeper into how the gem works. Aggregate column is added in one of
79
+ two ways:
80
+
81
+ * if :join_type option is not present - it's appended as subquery to SELECT
82
+ clause, eg:
83
+
84
+ SELECT posts.*, (SELECT count(*) AS comment_count FROM comments WHERE
85
+ (posts.id = post_id)) AS comment_count FROM "posts" ORDER BY comment_count
86
+ DESC
87
+
88
+ * if :join_type option is present - it's added as a subquery connected using
89
+ JOIN clause with join type specified, eg (:join_type => :right):
90
+
91
+ SELECT posts.*, comment_count FROM "posts" RIGHT JOIN (SELECT post_id,
92
+ count(*) AS comment_count FROM comments GROUP BY post_id) comment_count_join
93
+ ON posts.id = comment_count_join.post_id ORDER BY comment_count DESC
94
+
95
+ Now, each way has it's place.
96
+
97
+ In-select subquery:
98
+ * foreign key index is used (PostgreSQL at least)
99
+ * subquery executed only for rows fetched from main table
100
+
101
+ In-join subquery:
102
+ * with RIGHT join only fetches records from main table having results in
103
+ aggregate column (eg. only posts with any comments)
104
+
105
+ You can only decide between those two on a case by case basis. But generally: if
106
+ you only care about records having some meaningful values in aggregate column,
107
+ in-join might be better; if main table has some large record count, but you only
108
+ want to select some subset of those, in-select might save you some computation
109
+ time.
110
+
111
+ Rails 2
112
+ =======
113
+
114
+ NOTE: this is deprecated and I'm not sure if it even still works. But the code
115
+ is there, so it might be useful for someone.
116
+
117
+
118
+ Instead of aggregate_columns you have aggregate_column_options:
119
+
120
+ Post.aggregate_columns_options( :association => :comments )
121
+
122
+ which returns a Hash of options suitable to pass to .find call. You have
123
+ additional options: :joins and :conditions to be passed to the subquery, because
124
+ you don't have a Relation object to work on in a block.
42
125
 
43
126
  Now something really complicated - sum of votes for comments whose authors are
44
127
  active. Here's where :conditions and :joins options come in handy:
@@ -53,6 +136,9 @@ active. Here's where :conditions and :joins options come in handy:
53
136
  )
54
137
  )
55
138
 
139
+ :joins and :conditions are passed to the subquery, so they will determine which
140
+ comments are considered when calculating vote sum
141
+
56
142
  Important things to note here:
57
143
  * aggregate_column_options return :select, :joins and :order options, so those
58
144
  cannot be used for other purposes
@@ -60,7 +146,6 @@ Important things to note here:
60
146
  with normal find options (other than aforementioned ones). This means you can
61
147
  merge resulting options with eg. custom :conditions
62
148
 
63
-
64
149
  You may also define multiple aggregate columns in one call:
65
150
 
66
151
  Post.aggregate_columns_options(
@@ -68,20 +153,10 @@ You may also define multiple aggregate columns in one call:
68
153
  { :association => :tags, :result_column => :number_of_tags }
69
154
  )
70
155
 
71
-
72
156
  Yet another method to combine aggregate columns with other find options is to use scopes:
73
157
 
74
158
  Post.aggregate_columns_scope( :association => :comments ).scoped( ...
75
159
 
76
- Rails 3
77
- =======
78
-
79
- In Rails 3 you should use:
80
-
81
- Post.aggregate_colums( :association => :comments )
82
-
83
- which returns a full blown ActiveRecord::Relation object
84
-
85
160
  Thanks
86
161
  ======
87
162
 
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ # Now I have no idea why this doesn't work without specifying the task explicitly
4
+ require "rake/testtask"
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/*test.rb']
8
+ t.verbose = true
9
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "aggregate_columns/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "aggregate_columns"
7
+ s.version = AggregateColumns::VERSION
8
+ s.authors = ["Marek Janukowicz/Starware"]
9
+ s.email = ["marek@janukowicz.net"]
10
+ s.homepage = ""
11
+ s.summary = "Create and use aggregate columns in Rails applications"
12
+ s.description = ""
13
+
14
+ s.files = `hg manifest`.split("\n")
15
+ s.test_files = `hg manifest | grep ^test`.split("\n")
16
+ s.executables = `hg manifest | grep ^bin`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ # specify any dependencies here; for example:
20
+ # s.add_development_dependency "rspec"
21
+ s.add_runtime_dependency "activerecord", ">= 2"
22
+ s.add_development_dependency "rake"
23
+ s.add_development_dependency "activerecord", ">= 2"
24
+ s.add_development_dependency "activesupport", ">= 2"
25
+ s.add_development_dependency "activerecord-nulldb-adapter"
26
+
27
+ end
@@ -93,10 +93,10 @@ module AggregateColumns
93
93
 
94
94
  end
95
95
 
96
- # All versions
97
- ActiveRecord::Base.send( :extend, AggregateColumns::MethodsRails2 )
98
- if defined?( ActiveRecord::Relation )
96
+ if defined?( ActiveRecord::Relation ) # Rails 3
99
97
  ActiveRecord::Base.send( :extend, AggregateColumns::MethodsRails3 )
98
+ else # Rails 2
99
+ ActiveRecord::Base.send( :extend, AggregateColumns::MethodsRails2 )
100
100
  end
101
101
 
102
102
  ## Rails 2
@@ -0,0 +1,3 @@
1
+ module AggregateColumns
2
+ VERSION = "0.9.5"
3
+ end
@@ -0,0 +1,86 @@
1
+ # TODO: this test doesn't really work with Rails 2
2
+ require 'active_record'
3
+ require 'rails'
4
+
5
+ if Rails::VERSION::MAJOR == 2
6
+
7
+ require 'test_helper'
8
+
9
+ class Rails2Test < ActiveSupport::TestCase
10
+
11
+ class Post < FakeModel
12
+ end
13
+
14
+ class User < FakeModel
15
+ has_many :posts
16
+ end
17
+
18
+ def setup
19
+ @user = User.new
20
+ end
21
+
22
+ test "empty options" do
23
+ options = User.aggregate_columns_options
24
+ assert_equal "users.*", options[:select]
25
+ assert options[:order].blank?
26
+ assert options[:joins].blank?
27
+ end
28
+
29
+ test "empty hash as options should fail" do
30
+ assert_raise( ArgumentError ) do
31
+ options = User.aggregate_columns_options( {} )
32
+ end
33
+ end
34
+
35
+ test "only association" do
36
+ options = User.aggregate_columns_options( :association => :posts )
37
+ assert_equal "users.*, post_count", options[:select]
38
+ assert_equal "post_count DESC", options[:order]
39
+ 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]
40
+ end
41
+
42
+ test "column function" do
43
+ options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max )
44
+ assert_equal "users.*, posts_created_at_max", options[:select]
45
+ assert_equal "posts_created_at_max DESC", options[:order]
46
+ 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]
47
+ end
48
+
49
+ test "result_column" do
50
+ options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :result_column => "last_post_time" )
51
+ assert_equal "users.*, last_post_time", options[:select]
52
+ assert_equal "last_post_time DESC", options[:order]
53
+ 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]
54
+ end
55
+
56
+ test "join_type" do
57
+ options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :join_type => "RIGHT" )
58
+ assert_equal "users.*, posts_created_at_max", options[:select]
59
+ assert_equal "posts_created_at_max DESC", options[:order]
60
+ 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]
61
+ end
62
+
63
+ test "conditions" do
64
+ options = User.aggregate_columns_options( :association => :posts, :column => :created_at, :function => :max, :conditions => { :active => true } )
65
+ assert_equal "users.*, posts_created_at_max", options[:select]
66
+ assert_equal "posts_created_at_max DESC", options[:order]
67
+ 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]
68
+ end
69
+
70
+ test "joins" do
71
+ time = 2.days.ago
72
+ 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] )
73
+ assert_equal "users.*, posts_created_at_max", options[:select]
74
+ assert_equal "posts_created_at_max DESC", options[:order]
75
+ 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]
76
+ end
77
+
78
+ test "order" do
79
+ options = User.aggregate_columns_options( :association => :posts, :order => :asc )
80
+ assert_equal "users.*, post_count", options[:select]
81
+ assert_equal "post_count ASC", options[:order]
82
+ 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]
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,80 @@
1
+ require 'active_record'
2
+ require 'rails'
3
+
4
+ if Rails::VERSION::MAJOR == 3
5
+ require 'test/unit'
6
+ require 'aggregate_columns'
7
+
8
+ # Workaround for nulldb Rails 3.1 incompatibility
9
+ class Object
10
+ alias_method :returning, :tap
11
+ end
12
+
13
+ class Rails3Test < Test::Unit::TestCase
14
+
15
+ ActiveRecord::Base.establish_connection :adapter => :nulldb
16
+
17
+ class Post < ActiveRecord::Base
18
+ has_many :comments
19
+ end
20
+
21
+ class Comment < ActiveRecord::Base
22
+ belongs_to :post
23
+ end
24
+
25
+ def test_only_association
26
+ relation = Post.aggregate_columns( :association => :comments )
27
+ 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" )
29
+ assert_equal relation.order_values, ["comment_count DESC"]
30
+ assert_empty relation.where_values
31
+ assert_empty relation.joins_values
32
+ end
33
+
34
+ # Reorder doesn't work, probably I don't understand how it is supposed to work
35
+ #def test_reorder
36
+ # relation = Post.aggregate_columns( :association => :comments ).reorder( "posts.id ASC" )
37
+ #end
38
+
39
+ def test_function_and_column
40
+ relation = Post.aggregate_columns( :association => :comments, :function => :max, :column => :created_at )
41
+ 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" )
43
+ assert_equal relation.order_values, ["comments_created_at_max DESC"]
44
+ assert_empty relation.where_values
45
+ assert_empty relation.joins_values
46
+ end
47
+
48
+ def test_result_column
49
+ relation = Post.aggregate_columns( :association => :comments, :function => :max, :column => :created_at, :result_column => :max_created_at )
50
+ assert_equal 2, relation.select_values.count
51
+ assert relation.select_values.include?( "(SELECT max(created_at) AS max_created_at FROM comments WHERE (posts.id = post_id)) AS max_created_at" )
52
+ assert_equal relation.order_values, ["max_created_at DESC"]
53
+ assert_empty relation.where_values
54
+ assert_empty relation.joins_values
55
+ end
56
+
57
+ def test_right_join
58
+ relation = Post.aggregate_columns( :association => :comments, :join_type => :right )
59
+ assert_equal 2, relation.select_values.count
60
+ assert relation.select_values.include?( "comment_count" )
61
+ assert_equal relation.joins_values, ["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"]
62
+ assert_equal ["comment_count DESC"], relation.order_values
63
+ assert_empty relation.where_values
64
+ end
65
+
66
+ def test_where_clauses
67
+ relation = Post.where( :id => 2 ).aggregate_columns( :association => :comments ) { |rel| rel.where( :id => 1 ) }
68
+ 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
69
+ assert relation.select_values.include?( "(SELECT count(*) AS comment_count FROM comments WHERE comments.id = 1 AND (posts.id = post_id)) AS comment_count" )
70
+ end
71
+
72
+ def test_multiple_aggregates
73
+ relation = Post.aggregate_columns( :association => :comments, :join_type => :right ).aggregate_columns( :association => :comments ).aggregate_columns( :association => :comments, :function => :sum, :column => :vote, :result_column => :number_of_votes )
74
+ assert_empty relation.where_values
75
+ assert relation.select_values.include?( "comment_count" )
76
+ 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" )
77
+ end
78
+
79
+ end
80
+ end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # Rails 2 helper - doesn't really work, as do Rails 2 tests themselves
2
+
1
3
  require 'rubygems'
2
4
  require 'test/unit'
3
- gem 'activesupport'#, "< 3.0.0"
5
+ #gem 'activesupport'
4
6
  require 'active_support/test_case'
5
7
  require 'active_record'
6
8
  require 'active_record/base'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aggregate_columns
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 4
10
- version: 0.9.4
9
+ - 5
10
+ version: 0.9.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Marek Janukowicz/Starware
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-12-09 00:00:00 +01:00
18
+ date: 2012-01-03 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -32,6 +32,62 @@ dependencies:
32
32
  version: "2"
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rake
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: activerecord
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 7
58
+ segments:
59
+ - 2
60
+ version: "2"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: activesupport
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 7
72
+ segments:
73
+ - 2
74
+ version: "2"
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: activerecord-nulldb-adapter
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
35
91
  description: ""
36
92
  email:
37
93
  - marek@janukowicz.net
@@ -43,10 +99,14 @@ extra_rdoc_files: []
43
99
 
44
100
  files:
45
101
  - .hgignore
102
+ - Gemfile
46
103
  - README
47
104
  - Rakefile
105
+ - aggregate_columns.gemspec
48
106
  - lib/aggregate_columns.rb
49
- - test/aggregate_columns_test.rb
107
+ - lib/aggregate_columns/version.rb
108
+ - test/rails_2_test.rb
109
+ - test/rails_3_test.rb
50
110
  - test/test_helper.rb
51
111
  has_rdoc: true
52
112
  homepage: ""
@@ -83,5 +143,6 @@ signing_key:
83
143
  specification_version: 3
84
144
  summary: Create and use aggregate columns in Rails applications
85
145
  test_files:
86
- - test/aggregate_columns_test.rb
146
+ - test/rails_2_test.rb
147
+ - test/rails_3_test.rb
87
148
  - test/test_helper.rb
@@ -1,82 +0,0 @@
1
- require 'test_helper'
2
-
3
- class AggregateColumnsTest < ActiveSupport::TestCase
4
-
5
- class Post < FakeModel
6
- end
7
-
8
- class User < FakeModel
9
- has_many :posts
10
- end
11
-
12
- def setup
13
- @user = User.new
14
- end
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
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
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
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
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
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
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
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
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
78
-
79
- # TODO:
80
- # test multiple aggregates
81
- # test with real database
82
- end