ghazel-pacecar 1.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
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.
data/README.rdoc ADDED
@@ -0,0 +1,211 @@
1
+ == Pacecar
2
+
3
+ Pacecar adds named_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
+ 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.
10
+
11
+ == Usage
12
+
13
+ Assuming a database schema...
14
+
15
+ class CreateSchema < ActiveRecord::Migration
16
+ def self.up
17
+ create_table :users, :force => true do |t|
18
+ t.boolean :admin, :default => false, :null => false
19
+ t.datetime :approved_at
20
+ t.datetime :rejected_at
21
+ t.string :first_name
22
+ t.string :last_name
23
+ t.text :description
24
+ t.timestamps
25
+ end
26
+ create_table :posts, :force => true do |t|
27
+ t.string :owner_type
28
+ t.integer :owner_id
29
+ t.string :publication_state
30
+ t.string :post_type
31
+ t.timestamps
32
+ end
33
+ create_table :comments, :force => true do |t|
34
+ t.integer :user_id
35
+ t.text :description
36
+ t.timestamps
37
+ end
38
+ end
39
+ end
40
+
41
+ And some basic model declarations...
42
+
43
+ class User < ActiveRecord::Base
44
+ include Pacecar
45
+ has_many :posts, :as => :owner
46
+ has_many :comments
47
+ has_many :articles
48
+ has_ranking :comments
49
+ has_recent_records :comments
50
+ has_recent_records :articles, :comments
51
+ end
52
+
53
+ class Post < ActiveRecord::Base
54
+ include Pacecar
55
+ PUBLICATION_STATES = %w(Draft Submitted Rejected Accepted)
56
+ TYPES = %w(Free Open Private Anonymous PostModern)
57
+ belongs_to :owner, :polymorphic => true
58
+ has_state :publication_state
59
+ has_state :post_type, :with => TYPES
60
+ has_polymorph :owner
61
+ end
62
+
63
+ class Comment < ActiveRecord::Base
64
+ include Pacecar
65
+ belongs_to :user
66
+ end
67
+
68
+ class Article < ActiveRecord::Base
69
+ belongs_to :user
70
+ end
71
+
72
+ = All columns
73
+
74
+ Records where approved_at is not null, or where it is null...
75
+
76
+ User.approved_at_present
77
+ User.approved_at_missing
78
+
79
+ Records where first_name is not null, or where it is null...
80
+
81
+ User.first_name_present
82
+ User.first_name_missing
83
+
84
+ Records ordered by first_name (default to 'asc', can specify to override)...
85
+
86
+ User.by_first_name
87
+ User.by_first_name(:asc)
88
+ User.by_first_name(:desc)
89
+
90
+ Records where an attribute matches a search term (column LIKE "%term%")...
91
+
92
+ User.first_name_matches('John')
93
+
94
+ Records where an attribute starts or ends with a search term...
95
+
96
+ User.first_name_starts_with('A')
97
+ User.first_name_ends_with('a')
98
+
99
+ Records where an attribute matches exactly a term...
100
+
101
+ User.first_name_equals('John')
102
+
103
+ Records where any non-state text or string column matches term...
104
+
105
+ User.search_for('test')
106
+
107
+ Records where any of a list of columns match the term...
108
+
109
+ User.search_for 'test', :on => [:first_name, :last_name]
110
+
111
+ Records where all of a list of columns match the term...
112
+
113
+ User.search_for 'test', :on => [:first_name, :last_name], :require => :all
114
+
115
+ = Boolean columns
116
+
117
+ Records that are all admins or non-admins...
118
+
119
+ User.admin
120
+ User.not_admin
121
+
122
+ The "balance" (count of true minus false for column in question)...
123
+
124
+ User.admin_balance
125
+
126
+ = Datetime columns
127
+
128
+ Records approved before or after certain times...
129
+
130
+ User.approved_at_before(5.days.ago)
131
+ User.approved_at_after(4.weeks.ago)
132
+
133
+ Records with approved_at in the past or future...
134
+
135
+ User.approved_at_in_past
136
+ User.approved_at_in_future
137
+
138
+ Records with approved_at inside or outside of two times...
139
+
140
+ User.approved_at_inside(10.days.ago, 1.day.ago)
141
+ User.approved_at_outside(2.days.ago, 1.day.ago)
142
+
143
+ Records with certain year, month or day...
144
+
145
+ User.approved_at_in_year(2000)
146
+ User.approved_at_in_month(01)
147
+ User.approved_at_in_day(01)
148
+
149
+ Records with a duration (time delta between two columns) of, over or under a certain number of days...
150
+
151
+ User.with_duration_of(14, :approved_at, :rejected_at)
152
+ User.with_duration_over(14, :approved_at, :rejected_at)
153
+ User.with_duration_under(14, :approved_at, :rejected_at)
154
+
155
+ = Polymorphic relationships
156
+
157
+ Records which have an owner_type of User...
158
+
159
+ Post.for_owner_type(User)
160
+
161
+ = Associations
162
+
163
+ Records with the most and least associated records...
164
+
165
+ User.maximum_comments
166
+ User.minimum_comments
167
+
168
+ Records with associated records since a certain time...
169
+
170
+ User.recent_comments_since(2.days.ago)
171
+ User.recent_comments_and_posts_since(3.days.ago)
172
+ User.recent_comments_or_posts_since(4.days.ago)
173
+
174
+ = State columns
175
+
176
+ Records which are in a particular state, or not in a state...
177
+
178
+ Post.publication_state_draft
179
+ Post.post_type_not_open
180
+
181
+ Query methods on instances to check state...
182
+
183
+ Post.first.publication_state_draft?
184
+ Post.last.post_type_not_open?
185
+
186
+ = Limits
187
+
188
+ First x records...
189
+
190
+ User.limited(10)
191
+
192
+ = Named scopes
193
+
194
+ Because these are all named_scope, you can combine them.
195
+
196
+ 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...
197
+
198
+ User.first_name_present.admin.approved_at_before(2.weeks.ago).by_first_name
199
+
200
+ To get the top 10 commenters...
201
+
202
+ User.maximim_comments.limited(10)
203
+
204
+ = Supported Databases
205
+
206
+ * MySQL
207
+ * SQLite
208
+
209
+ = License
210
+
211
+ Pacecar is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'pacecar'
data/lib/pacecar.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'pacecar/associations'
2
+ require 'pacecar/boolean'
3
+ require 'pacecar/datetime'
4
+ require 'pacecar/duration'
5
+ require 'pacecar/helpers'
6
+ require 'pacecar/limit'
7
+ require 'pacecar/order'
8
+ require 'pacecar/polymorph'
9
+ require 'pacecar/presence'
10
+ require 'pacecar/ranking'
11
+ require 'pacecar/search'
12
+ require 'pacecar/state'
13
+
14
+ module Pacecar
15
+ def self.included(base)
16
+ base.class_eval do
17
+ include Pacecar::Associations
18
+ include Pacecar::Boolean
19
+ include Pacecar::Datetime
20
+ include Pacecar::Duration
21
+ include Pacecar::Limit
22
+ include Pacecar::Order
23
+ include Pacecar::Polymorph
24
+ include Pacecar::Presence
25
+ include Pacecar::Ranking
26
+ include Pacecar::Search
27
+ include Pacecar::State
28
+ end
29
+ end
30
+ end
31
+
32
+ ActiveRecord::Base.send :include, Pacecar::Helpers
@@ -0,0 +1,39 @@
1
+ module Pacecar
2
+ module Associations
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def has_recent_records(*names)
10
+ names.each do |name|
11
+ named_scope "recent_#{name}_since".to_sym, lambda { |since|
12
+ {
13
+ :conditions => [conditions_for_name(name), { :since_time => since }]
14
+ }
15
+ }
16
+ end
17
+ unless names.first == names.last
18
+ named_scope "recent_#{names.join('_or_')}_since".to_sym, lambda { |since|
19
+ {
20
+ :conditions => [names.collect { |name| conditions_for_name(name) }.join(' or '), { :since_time => since }]
21
+ }
22
+ }
23
+ named_scope "recent_#{names.join('_and_')}_since".to_sym, lambda { |since|
24
+ {
25
+ :conditions => [names.collect { |name| conditions_for_name(name) }.join(' and '), { :since_time => since }]
26
+ }
27
+ }
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def conditions_for_name(name)
34
+ "((select count(*) from \"#{name}\" where \"#{name}\".#{reflections[name].primary_key_name} = #{quoted_table_name}.id and \"#{name}\".created_at > :since_time) > 0)"
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ module Pacecar
2
+ module Boolean
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_boolean_scopes
10
+ base.send :define_balance_count
11
+ end
12
+
13
+ protected
14
+
15
+ def define_boolean_scopes
16
+ boolean_column_names.each do |name|
17
+ named_scope name.to_sym, :conditions => ["#{quoted_table_name}.#{name} = ?", true]
18
+ named_scope "not_#{name}".to_sym, :conditions => ["#{quoted_table_name}.#{name} = ?", false]
19
+ end
20
+ end
21
+
22
+ def define_balance_count
23
+ boolean_column_names.each do |name|
24
+ self.class_eval %Q{
25
+ def self.#{name}_balance
26
+ #{name}.count - not_#{name}.count
27
+ end
28
+ }
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,68 @@
1
+ module Pacecar
2
+ module Datetime
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_datetime_scopes
10
+ end
11
+
12
+ protected
13
+
14
+ def define_datetime_scopes
15
+ datetime_column_names.each do |name|
16
+ define_before_after_scopes(name)
17
+ define_past_future_scopes(name)
18
+ define_inside_outside_scopes(name)
19
+ define_in_date_scopes(name)
20
+ end
21
+ end
22
+
23
+ def define_before_after_scopes(name)
24
+ named_scope "#{name}_before".to_sym, lambda { |time|
25
+ { :conditions => ["#{quoted_table_name}.#{name} <= ?", time] }
26
+ }
27
+ named_scope "#{name}_after".to_sym, lambda { |time|
28
+ { :conditions => ["#{quoted_table_name}.#{name} >= ?", time] }
29
+ }
30
+ end
31
+
32
+ def define_past_future_scopes(name)
33
+ named_scope "#{name}_in_past", lambda {
34
+ { :conditions => ["#{quoted_table_name}.#{name} <= ?", now] }
35
+ }
36
+ named_scope "#{name}_in_future", lambda {
37
+ { :conditions => ["#{quoted_table_name}.#{name} >= ?", now] }
38
+ }
39
+ end
40
+
41
+ def define_inside_outside_scopes(name)
42
+ named_scope "#{name}_inside".to_sym, lambda { |start, stop|
43
+ { :conditions => ["#{quoted_table_name}.#{name} >= ? and #{quoted_table_name}.#{name} <= ?", start, stop] }
44
+ }
45
+ named_scope "#{name}_outside".to_sym, lambda { |start, stop|
46
+ { :conditions => ["#{quoted_table_name}.#{name} <= ? and #{quoted_table_name}.#{name} >= ?", start, stop] }
47
+ }
48
+ end
49
+
50
+ def define_in_date_scopes(name)
51
+ named_scope "#{name}_in_year".to_sym, lambda { |year|
52
+ { :conditions => ["year(#{quoted_table_name}.#{name}) = ?", year] }
53
+ }
54
+ named_scope "#{name}_in_month".to_sym, lambda { |month|
55
+ { :conditions => ["month(#{quoted_table_name}.#{name}) = ?", month] }
56
+ }
57
+ named_scope "#{name}_in_day".to_sym, lambda { |day|
58
+ { :conditions => ["day(#{quoted_table_name}.#{name}) = ?", day] }
59
+ }
60
+ end
61
+
62
+ def now
63
+ defined?(Time.zone_default) && Time.zone_default ? Time.zone_default.now : Time.now
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,28 @@
1
+ module Pacecar
2
+ module Duration
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_duration_scopes
10
+ end
11
+
12
+ protected
13
+
14
+ def define_duration_scopes
15
+ named_scope :with_duration_of, lambda { |duration, start, stop|
16
+ { :conditions => ["datediff(#{quoted_table_name}.#{start}, #{quoted_table_name}.#{stop}) = ?", duration] }
17
+ }
18
+ named_scope :with_duration_over, lambda { |duration, start, stop|
19
+ { :conditions => ["datediff(#{quoted_table_name}.#{start}, #{quoted_table_name}.#{stop}) > ?", duration] }
20
+ }
21
+ named_scope :with_duration_under, lambda { |duration, start, stop|
22
+ { :conditions => ["datediff(#{quoted_table_name}.#{start}, #{quoted_table_name}.#{stop}) < ?", duration] }
23
+ }
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,54 @@
1
+ module Pacecar
2
+ module Helpers
3
+
4
+ mattr_accessor :options
5
+ self.options = {
6
+ :state_pattern => /_(type|state)$/i,
7
+ :default_limit => 10
8
+ }
9
+
10
+ def self.included(base)
11
+ base.extend ClassMethods
12
+ end
13
+
14
+ module ClassMethods
15
+
16
+ def safe_columns
17
+ begin
18
+ columns
19
+ rescue ActiveRecord::StatementInvalid # If the table does not exist
20
+ Array.new
21
+ end
22
+ end
23
+
24
+ def safe_column_names
25
+ safe_columns.collect(&:name)
26
+ end
27
+
28
+ def column_names_for_type(*types)
29
+ safe_columns.select { |column| types.include? column.type }.collect(&:name)
30
+ end
31
+
32
+ def column_names_without_type(*types)
33
+ safe_columns.select { |column| ! types.include? column.type }.collect(&:name)
34
+ end
35
+
36
+ def boolean_column_names
37
+ column_names_for_type :boolean
38
+ end
39
+
40
+ def datetime_column_names
41
+ column_names_for_type :datetime, :date
42
+ end
43
+
44
+ def text_and_string_column_names
45
+ column_names_for_type :text, :string
46
+ end
47
+
48
+ def non_state_text_and_string_columns
49
+ text_and_string_column_names.reject { |name| name =~ Pacecar::Helpers.options[:state_pattern] }
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ module Pacecar
2
+ module Limit
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_limit_scopes
10
+ end
11
+
12
+ protected
13
+
14
+ def define_limit_scopes
15
+ named_scope :limited, lambda { |*args|
16
+ { :limit => args.flatten.first || (defined?(per_page) ? per_page : Pacecar::Helpers.options[:default_limit]) }
17
+ }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ module Pacecar
2
+ module Order
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_order_scopes
10
+ end
11
+
12
+ protected
13
+
14
+ def define_order_scopes
15
+ safe_columns.collect(&:name).each do |name|
16
+ named_scope "by_#{name}".to_sym, lambda { |*args|
17
+ { :order => "#{quoted_table_name}.#{name} #{args.flatten.first || 'asc'}" }
18
+ }
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ module Pacecar
2
+ module Polymorph
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def has_polymorph(name)
10
+ named_scope "for_#{name}_type".to_sym, lambda { |type|
11
+ { :conditions => ["#{quoted_table_name}.#{name}_type = ?", type.to_s] }
12
+ }
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module Pacecar
2
+ module Presence
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_presence_scopes
10
+ end
11
+
12
+ protected
13
+
14
+ def define_presence_scopes
15
+ column_names_without_type(:boolean).each do |name|
16
+ named_scope "#{name}_present".to_sym, :conditions => "#{quoted_table_name}.#{name} is not null"
17
+ named_scope "#{name}_missing".to_sym, :conditions => "#{quoted_table_name}.#{name} is null"
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ module Pacecar
2
+ module Ranking
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def has_ranking(association)
10
+ define_ranking_scope association, :maximum, :desc
11
+ define_ranking_scope association, :minimum, :asc
12
+ end
13
+
14
+ protected
15
+
16
+ def define_ranking_scope(association, name, direction)
17
+ named_scope "#{name}_#{association}",
18
+ :joins => "inner join #{association} on #{association}.#{reflections[association].primary_key_name} = #{quoted_table_name}.#{primary_key}",
19
+ :select => "#{quoted_table_name}.*, count(#{quoted_table_name}.#{primary_key}) as #{association}_count",
20
+ :group => "#{association}.#{reflections[association].primary_key_name}",
21
+ :order => "#{association}_count #{direction}"
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ module Pacecar
2
+ module Search
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def self.extended(base)
9
+ base.send :define_search_scopes
10
+ base.send :define_basic_search_scope
11
+ end
12
+
13
+ protected
14
+
15
+ def define_search_scopes
16
+ safe_column_names.each do |name|
17
+ named_scope "#{name}_equals".to_sym, lambda { |query|
18
+ { :conditions => { name.to_sym => query } }
19
+ }
20
+ end
21
+ text_and_string_column_names.each do |name|
22
+ named_scope "#{name}_matches".to_sym, lambda { |query|
23
+ { :conditions => ["#{quoted_table_name}.#{name} like :query", { :query => "%#{query}%" }] }
24
+ }
25
+ named_scope "#{name}_starts_with".to_sym, lambda { |query|
26
+ { :conditions => ["#{quoted_table_name}.#{name} like :query", { :query => "#{query}%" }] }
27
+ }
28
+ named_scope "#{name}_ends_with".to_sym, lambda { |query|
29
+ { :conditions => ["#{quoted_table_name}.#{name} like :query", { :query => "%#{query}" }] }
30
+ }
31
+ end
32
+ end
33
+
34
+ def define_basic_search_scope
35
+ named_scope :search_for, lambda { |*args|
36
+ opts = args.extract_options!
37
+ query = args.flatten.first
38
+ columns = opts[:on] || non_state_text_and_string_columns
39
+ joiner = opts[:require].eql?(:all) ? 'and' : 'or'
40
+ match = columns.collect { |name| "#{quoted_table_name}.#{name} like :query" }.join(" #{joiner} ")
41
+ { :conditions => [match, { :query => "%#{query}%" } ] }
42
+ }
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ module Pacecar
2
+ module State
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def has_state(*names)
10
+ opts = names.extract_options!
11
+ names.each do |name|
12
+ constant = opts[:with] || const_get(name.to_s.pluralize.upcase)
13
+ constant.each do |state|
14
+ named_scope "#{name}_#{state.downcase}".to_sym, :conditions => ["#{quoted_table_name}.#{name} = ?", state]
15
+ named_scope "#{name}_not_#{state.downcase}".to_sym, :conditions => ["#{quoted_table_name}.#{name} <> ?", state]
16
+ self.class_eval %Q{
17
+ def #{name}_#{state.downcase}?
18
+ #{name} == '#{state}'
19
+ end
20
+ def #{name}_not_#{state.downcase}?
21
+ #{name} != '#{state}'
22
+ end
23
+ }
24
+ end
25
+ named_scope "#{name}".to_sym, lambda { |state|
26
+ { :conditions => ["#{quoted_table_name}.#{name} = ?", state] }
27
+ }
28
+ named_scope "#{name}_not".to_sym, lambda { |state|
29
+ { :conditions => ["#{quoted_table_name}.#{name} <> ?", state] }
30
+ }
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ghazel-pacecar
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matt Jankowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-30 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Generated scopes for ActiveRecord classes.
17
+ email: mjankowski@thoughtbot.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - init.rb
26
+ - lib/pacecar/associations.rb
27
+ - lib/pacecar/boolean.rb
28
+ - lib/pacecar/datetime.rb
29
+ - lib/pacecar/duration.rb
30
+ - lib/pacecar/helpers.rb
31
+ - lib/pacecar/limit.rb
32
+ - lib/pacecar/order.rb
33
+ - lib/pacecar/polymorph.rb
34
+ - lib/pacecar/presence.rb
35
+ - lib/pacecar/ranking.rb
36
+ - lib/pacecar/search.rb
37
+ - lib/pacecar/state.rb
38
+ - lib/pacecar.rb
39
+ - MIT-LICENSE
40
+ - README.rdoc
41
+ has_rdoc: true
42
+ homepage: http://github.com/thoughtbot/pacecar
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.5
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Pacecar adds named_scope methods to ActiveRecord classes via database column introspection.
69
+ test_files: []
70
+