pacecar 1.4.4 → 1.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/MIT-LICENSE +20 -22
  2. data/README.md +277 -0
  3. data/lib/pacecar/ranking.rb +33 -6
  4. metadata +6 -9
  5. data/README.rdoc +0 -242
data/MIT-LICENSE CHANGED
@@ -1,22 +1,20 @@
1
- Copyright (c) 2008, Matt Jankowski & thoughtbot, inc.
2
-
3
- Permission is hereby granted, free of charge, to any person
4
- obtaining a copy of this software and associated documentation
5
- files (the "Software"), to deal in the Software without
6
- restriction, including without limitation the rights to use,
7
- copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- copies of the Software, and to permit persons to whom the
9
- Software is furnished to do so, subject to the following
10
- conditions:
11
-
12
- The above copyright notice and this permission notice shall be
13
- included in all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
- OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2008, Matt Jankowski & thoughtbot, inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,277 @@
1
+ Pacecar
2
+ =======
3
+
4
+ Pacecar adds scope methods and other common functionality to ActiveRecord classes via database column introspection.
5
+
6
+ Pacecar automatically includes the Pacecar::Helpers module into all ActiveRecord::Base classes.
7
+
8
+ To get all Pacecar functionality, you need to "include Pacecar" in your class.
9
+
10
+ class User < ActiveRecord::Base
11
+ include Pacecar
12
+ end
13
+
14
+ To get some subset (for example, only the state functionality), you can do something like "include Pacecar::State" to get only the module(s) you want.
15
+
16
+ class Post < ActiveRecord::Base
17
+ include Pacecar::State
18
+ end
19
+
20
+ Pacecar supports mysql, postgres and sqlite database drivers.
21
+
22
+ Installation
23
+ ------------
24
+
25
+ For rails 3, just include in your Gemfile
26
+
27
+ gem 'pacecar'
28
+
29
+ For prior rails versions, there is a rails2 branch to use:
30
+
31
+ gem 'pacecar', :git => 'git://github.com/thoughtbot/pacecar.git', :branch => 'rails2'
32
+
33
+ Usage
34
+ -----
35
+
36
+ Assuming a database schema...
37
+
38
+ class CreateSchema < ActiveRecord::Migration
39
+ def self.up
40
+ create_table :users, :force => true do |t|
41
+ t.boolean :admin, :default => false, :null => false
42
+ t.datetime :approved_at
43
+ t.datetime :rejected_at
44
+ t.string :first_name
45
+ t.string :last_name
46
+ t.text :description
47
+ t.timestamps
48
+ end
49
+ create_table :posts, :force => true do |t|
50
+ t.string :owner_type
51
+ t.integer :owner_id
52
+ t.string :publication_state
53
+ t.string :post_type
54
+ t.timestamps
55
+ end
56
+ create_table :comments, :force => true do |t|
57
+ t.integer :user_id
58
+ t.text :description
59
+ t.integer :rating
60
+ t.timestamps
61
+ end
62
+ end
63
+ end
64
+
65
+ And some basic model declarations...
66
+
67
+ class User < ActiveRecord::Base
68
+ include Pacecar
69
+ has_many :posts, :as => :owner
70
+ has_many :comments
71
+ has_many :articles
72
+ has_ranking :comments
73
+ has_recent_records :comments
74
+ has_recent_records :articles, :comments
75
+ has_calculated_records :comments, :on => :rating
76
+ end
77
+
78
+ class Post < ActiveRecord::Base
79
+ include Pacecar
80
+ PUBLICATION_STATES = %w(Draft Submitted Rejected Accepted)
81
+ TYPES = %w(Free Open Private Anonymous PostModern)
82
+ belongs_to :owner, :polymorphic => true
83
+ has_state :publication_state
84
+ has_state :post_type, :with => TYPES
85
+ has_polymorph :owner
86
+ end
87
+
88
+ class Comment < ActiveRecord::Base
89
+ include Pacecar
90
+ belongs_to :user
91
+ end
92
+
93
+ class Article < ActiveRecord::Base
94
+ belongs_to :user
95
+ end
96
+
97
+ All columns
98
+ -----------
99
+
100
+ Records where approved_at is not null, or where it is null...
101
+
102
+ User.approved_at_present
103
+ User.approved_at_missing
104
+
105
+ Records where first_name is not null, or where it is null...
106
+
107
+ User.first_name_present
108
+ User.first_name_missing
109
+
110
+ Records ordered by first_name (default to 'asc', can specify to override)...
111
+
112
+ User.by_first_name
113
+ User.by_first_name(:asc)
114
+ User.by_first_name(:desc)
115
+
116
+ Records where an attribute matches a search term (column LIKE "%term%")...
117
+
118
+ User.first_name_matches('John')
119
+
120
+ Records where an attribute starts or ends with a search term...
121
+
122
+ User.first_name_starts_with('A')
123
+ User.first_name_ends_with('a')
124
+
125
+ Records where an attribute matches exactly a term...
126
+
127
+ User.first_name_equals('John')
128
+
129
+ Records where any non-state text or string column matches term...
130
+
131
+ User.search_for('test')
132
+
133
+ Records where any of a list of columns match the term...
134
+
135
+ User.search_for 'test', :on => [:first_name, :last_name]
136
+
137
+ Records where all of a list of columns match the term...
138
+
139
+ User.search_for 'test', :on => [:first_name, :last_name], :require => :all
140
+
141
+ Boolean columns
142
+ ---------------
143
+
144
+ Records that are all admins or non-admins...
145
+
146
+ User.admin
147
+ User.not_admin
148
+
149
+ The "balance" (count of true minus false for column in question)...
150
+
151
+ User.admin_balance
152
+
153
+ Datetime columns
154
+ ----------------
155
+
156
+ Records approved before or after certain times...
157
+
158
+ User.approved_at_before(5.days.ago)
159
+ User.approved_at_after(4.weeks.ago)
160
+
161
+ Records with approved_at in the past or future...
162
+
163
+ User.approved_at_in_past
164
+ User.approved_at_in_future
165
+
166
+ Records with approved_at inside or outside of two times...
167
+
168
+ User.approved_at_inside(10.days.ago, 1.day.ago)
169
+ User.approved_at_outside(2.days.ago, 1.day.ago)
170
+
171
+ Records with certain year, month or day...
172
+
173
+ User.approved_at_in_year(2000)
174
+ User.approved_at_in_month(01)
175
+ User.approved_at_in_day(01)
176
+
177
+ Records with a duration (time delta between two columns) of, over or under a certain number of days...
178
+
179
+ User.with_duration_of(14, :approved_at, :rejected_at)
180
+ User.with_duration_over(14, :approved_at, :rejected_at)
181
+ User.with_duration_under(14, :approved_at, :rejected_at)
182
+
183
+ Polymorphic relationships
184
+ -------------------------
185
+
186
+ Records which have an owner_type of User...
187
+
188
+ Post.for_owner_type(User)
189
+
190
+ Associations
191
+ ------------
192
+
193
+ Records with the most and least associated records...
194
+
195
+ User.maximum_comments
196
+ User.minimum_comments
197
+
198
+ Records with associated records since a certain time...
199
+
200
+ User.recent_comments_since(2.days.ago)
201
+ User.recent_comments_and_posts_since(3.days.ago)
202
+ User.recent_comments_or_posts_since(4.days.ago)
203
+
204
+ Records with highest and lowest association column average...
205
+
206
+ User.by_comments_highest_rating_average
207
+ User.by_comments_lowest_rating_average
208
+
209
+ Records with highest and lowest association column total...
210
+
211
+ User.by_comments_highest_rating_total
212
+ User.by_comments_lowest_rating_total
213
+
214
+ State columns
215
+ -------------
216
+
217
+ Records which are in a particular state, or not in a state...
218
+
219
+ Post.publication_state_draft
220
+ Post.post_type_not_open
221
+
222
+ Query methods on instances to check state...
223
+
224
+ Post.first.publication_state_draft?
225
+ Post.last.post_type_not_open?
226
+
227
+ Numeric columns
228
+ ---------------
229
+
230
+ Records which are greater than or less than a certain value...
231
+
232
+ User.age_greater_than(21)
233
+ User.age_greater_than_or_equal_to(21)
234
+ User.age_less_than(21)
235
+ User.age_less_than_or_equal_to(21)
236
+
237
+ Limits
238
+ ------
239
+
240
+ First x records...
241
+
242
+ User.limited(10)
243
+
244
+ Named scopes
245
+ ------------
246
+
247
+ Because these are all scope, you can combine them.
248
+
249
+ To get all users that have a first_name set, who are admins and approved more than 2 weeks ago, ordered by their first name...
250
+
251
+ User.first_name_present.admin.approved_at_before(2.weeks.ago).by_first_name
252
+
253
+ To get the top 10 commenters...
254
+
255
+ User.maximim_comments.limited(10)
256
+
257
+ Supported Databases
258
+ -------------------
259
+
260
+ * MySQL
261
+ * SQLite
262
+
263
+ Credits
264
+ -------
265
+
266
+ ![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
267
+
268
+ Pacecar is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
269
+
270
+ Thank you to all [the contributors](https://github.com/thoughtbot/pacecar/contributors)!
271
+
272
+ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
273
+
274
+ License
275
+ -------
276
+
277
+ Pacecar is Copyright © 2008-2011 thoughtbot. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
@@ -11,14 +11,41 @@ module Pacecar
11
11
  define_ranking_scope association, :minimum, :asc
12
12
  end
13
13
 
14
+ def has_calculated_records(*names)
15
+ opts = names.extract_options!
16
+ names.each do |association_name|
17
+ *columns = opts[:on] || []
18
+ columns.flatten.each do |column|
19
+ define_calculated_scope association_name, column, :average, :avg
20
+ define_calculated_scope association_name, column, :total, :sum
21
+ define_calculated_scope association_name, column, :count, :count
22
+ end
23
+ end
24
+ end
25
+
14
26
  protected
15
27
 
16
- def define_ranking_scope(association, name, direction)
17
- scope "#{name}_#{association}",
18
- :select => "#{quoted_table_name}.*, count(#{reflections[association].quoted_table_name}.#{connection.quote_column_name reflections[association].primary_key_name}) as #{association}_count",
19
- :joins => "inner join #{association} on #{association}.#{reflections[association].primary_key_name} = #{quoted_table_name}.#{connection.quote_column_name primary_key}",
20
- :group => safe_column_names.collect { |name| "#{quoted_table_name}.#{connection.quote_column_name(name)}" }.join(', '),
21
- :order => "#{association}_count #{direction}"
28
+ def define_ranking_scope(association, direction_name, direction)
29
+ scope "#{direction_name}_#{association}", {
30
+ :select => "#{quoted_table_name}.*, count(#{reflections[association].quoted_table_name}.#{connection.quote_column_name reflections[association].primary_key_name}) as #{association}_count",
31
+ :order => "#{association}_count #{direction}"
32
+ }.merge(association_group_and_join(association))
33
+ end
34
+
35
+ def define_calculated_scope(association_name, column, function_name, function_method)
36
+ { 'highest' => 'desc', 'lowest' => 'asc' }.each do |direction_name, direction|
37
+ scope "by_#{association_name}_#{direction_name}_#{column}_#{function_name}".to_sym, {
38
+ :select => "#{quoted_table_name}.*, #{function_method}(#{connection.quote_table_name(association_name)}.#{connection.quote_column_name column}) as #{association_name}_#{column}_#{function_name}",
39
+ :order => "#{association_name}_#{column}_#{function_name} #{direction}"
40
+ }.merge(association_group_and_join(association_name))
41
+ end
42
+ end
43
+
44
+ def association_group_and_join(association_name)
45
+ {
46
+ :joins => "inner join #{connection.quote_table_name(association_name)} on #{connection.quote_table_name(association_name)}.#{connection.quote_column_name reflections[association_name].primary_key_name} = #{quoted_table_name}.#{connection.quote_column_name primary_key}",
47
+ :group => safe_column_names.collect { |column_name| "#{quoted_table_name}.#{connection.quote_column_name(column_name)}" }.join(', ')
48
+ }
22
49
  end
23
50
 
24
51
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pacecar
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
5
4
  prerelease: false
6
5
  segments:
7
6
  - 1
8
7
  - 4
9
- - 4
10
- version: 1.4.4
8
+ - 5
9
+ version: 1.4.5
11
10
  platform: ruby
12
11
  authors:
13
12
  - Matt Jankowski
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-12-11 00:00:00 -05:00
17
+ date: 2011-01-20 00:00:00 -05:00
19
18
  default_executable:
20
19
  dependencies: []
21
20
 
@@ -25,11 +24,11 @@ executables: []
25
24
 
26
25
  extensions: []
27
26
 
28
- extra_rdoc_files:
29
- - README.rdoc
27
+ extra_rdoc_files: []
28
+
30
29
  files:
31
30
  - init.rb
32
- - README.rdoc
31
+ - README.md
33
32
  - MIT-LICENSE
34
33
  - lib/pacecar/associations.rb
35
34
  - lib/pacecar/boolean.rb
@@ -59,7 +58,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
59
58
  requirements:
60
59
  - - ">="
61
60
  - !ruby/object:Gem::Version
62
- hash: 3
63
61
  segments:
64
62
  - 0
65
63
  version: "0"
@@ -68,7 +66,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
66
  requirements:
69
67
  - - ">="
70
68
  - !ruby/object:Gem::Version
71
- hash: 3
72
69
  segments:
73
70
  - 0
74
71
  version: "0"
data/README.rdoc DELETED
@@ -1,242 +0,0 @@
1
- == Pacecar
2
-
3
- Pacecar adds scope methods and other common functionality to ActiveRecord classes via database column introspection.
4
-
5
- Pacecar automatically includes the Pacecar::Helpers module into all ActiveRecord::Base classes.
6
-
7
- To get all Pacecar functionality, you need to "include Pacecar" in your class.
8
-
9
- class User < ActiveRecord::Base
10
- include Pacecar
11
- end
12
-
13
- To get some subset (for example, only the state functionality), you can do something like "include Pacecar::State" to get only the module(s) you want.
14
-
15
- class Post < ActiveRecord::Base
16
- include Pacecar::State
17
- end
18
-
19
- Pacecar supports mysql, postgres and sqlite database drivers.
20
-
21
-
22
- == Installation
23
-
24
- For rails 3, just include in your Gemfile
25
-
26
- gem 'pacecar'
27
-
28
- For prior rails versions, there is a rails2 branch to use:
29
-
30
- gem 'pacecar', :git => 'git://github.com/thoughtbot/pacecar.git', :branch => 'rails2'
31
-
32
-
33
- == Usage
34
-
35
- Assuming a database schema...
36
-
37
- class CreateSchema < ActiveRecord::Migration
38
- def self.up
39
- create_table :users, :force => true do |t|
40
- t.boolean :admin, :default => false, :null => false
41
- t.datetime :approved_at
42
- t.datetime :rejected_at
43
- t.string :first_name
44
- t.string :last_name
45
- t.text :description
46
- t.timestamps
47
- end
48
- create_table :posts, :force => true do |t|
49
- t.string :owner_type
50
- t.integer :owner_id
51
- t.string :publication_state
52
- t.string :post_type
53
- t.timestamps
54
- end
55
- create_table :comments, :force => true do |t|
56
- t.integer :user_id
57
- t.text :description
58
- t.timestamps
59
- end
60
- end
61
- end
62
-
63
- And some basic model declarations...
64
-
65
- class User < ActiveRecord::Base
66
- include Pacecar
67
- has_many :posts, :as => :owner
68
- has_many :comments
69
- has_many :articles
70
- has_ranking :comments
71
- has_recent_records :comments
72
- has_recent_records :articles, :comments
73
- end
74
-
75
- class Post < ActiveRecord::Base
76
- include Pacecar
77
- PUBLICATION_STATES = %w(Draft Submitted Rejected Accepted)
78
- TYPES = %w(Free Open Private Anonymous PostModern)
79
- belongs_to :owner, :polymorphic => true
80
- has_state :publication_state
81
- has_state :post_type, :with => TYPES
82
- has_polymorph :owner
83
- end
84
-
85
- class Comment < ActiveRecord::Base
86
- include Pacecar
87
- belongs_to :user
88
- end
89
-
90
- class Article < ActiveRecord::Base
91
- belongs_to :user
92
- end
93
-
94
- = All columns
95
-
96
- Records where approved_at is not null, or where it is null...
97
-
98
- User.approved_at_present
99
- User.approved_at_missing
100
-
101
- Records where first_name is not null, or where it is null...
102
-
103
- User.first_name_present
104
- User.first_name_missing
105
-
106
- Records ordered by first_name (default to 'asc', can specify to override)...
107
-
108
- User.by_first_name
109
- User.by_first_name(:asc)
110
- User.by_first_name(:desc)
111
-
112
- Records where an attribute matches a search term (column LIKE "%term%")...
113
-
114
- User.first_name_matches('John')
115
-
116
- Records where an attribute starts or ends with a search term...
117
-
118
- User.first_name_starts_with('A')
119
- User.first_name_ends_with('a')
120
-
121
- Records where an attribute matches exactly a term...
122
-
123
- User.first_name_equals('John')
124
-
125
- Records where any non-state text or string column matches term...
126
-
127
- User.search_for('test')
128
-
129
- Records where any of a list of columns match the term...
130
-
131
- User.search_for 'test', :on => [:first_name, :last_name]
132
-
133
- Records where all of a list of columns match the term...
134
-
135
- User.search_for 'test', :on => [:first_name, :last_name], :require => :all
136
-
137
- = Boolean columns
138
-
139
- Records that are all admins or non-admins...
140
-
141
- User.admin
142
- User.not_admin
143
-
144
- The "balance" (count of true minus false for column in question)...
145
-
146
- User.admin_balance
147
-
148
- = Datetime columns
149
-
150
- Records approved before or after certain times...
151
-
152
- User.approved_at_before(5.days.ago)
153
- User.approved_at_after(4.weeks.ago)
154
-
155
- Records with approved_at in the past or future...
156
-
157
- User.approved_at_in_past
158
- User.approved_at_in_future
159
-
160
- Records with approved_at inside or outside of two times...
161
-
162
- User.approved_at_inside(10.days.ago, 1.day.ago)
163
- User.approved_at_outside(2.days.ago, 1.day.ago)
164
-
165
- Records with certain year, month or day...
166
-
167
- User.approved_at_in_year(2000)
168
- User.approved_at_in_month(01)
169
- User.approved_at_in_day(01)
170
-
171
- Records with a duration (time delta between two columns) of, over or under a certain number of days...
172
-
173
- User.with_duration_of(14, :approved_at, :rejected_at)
174
- User.with_duration_over(14, :approved_at, :rejected_at)
175
- User.with_duration_under(14, :approved_at, :rejected_at)
176
-
177
- = Polymorphic relationships
178
-
179
- Records which have an owner_type of User...
180
-
181
- Post.for_owner_type(User)
182
-
183
- = Associations
184
-
185
- Records with the most and least associated records...
186
-
187
- User.maximum_comments
188
- User.minimum_comments
189
-
190
- Records with associated records since a certain time...
191
-
192
- User.recent_comments_since(2.days.ago)
193
- User.recent_comments_and_posts_since(3.days.ago)
194
- User.recent_comments_or_posts_since(4.days.ago)
195
-
196
- = State columns
197
-
198
- Records which are in a particular state, or not in a state...
199
-
200
- Post.publication_state_draft
201
- Post.post_type_not_open
202
-
203
- Query methods on instances to check state...
204
-
205
- Post.first.publication_state_draft?
206
- Post.last.post_type_not_open?
207
-
208
- = Numeric columns
209
-
210
- Records which are greater than or less than a certain value...
211
-
212
- User.age_greater_than(21)
213
- User.age_greater_than_or_equal_to(21)
214
- User.age_less_than(21)
215
- User.age_less_than_or_equal_to(21)
216
-
217
- = Limits
218
-
219
- First x records...
220
-
221
- User.limited(10)
222
-
223
- = Named scopes
224
-
225
- Because these are all scope, you can combine them.
226
-
227
- To get all users that have a first_name set, who are admins and approved more than 2 weeks ago, ordered by their first name...
228
-
229
- User.first_name_present.admin.approved_at_before(2.weeks.ago).by_first_name
230
-
231
- To get the top 10 commenters...
232
-
233
- User.maximim_comments.limited(10)
234
-
235
- = Supported Databases
236
-
237
- * MySQL
238
- * SQLite
239
-
240
- = License
241
-
242
- Pacecar is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.