pacecar 1.4.3 → 1.4.4
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/lib/pacecar.rb +34 -0
- data/lib/pacecar/associations.rb +39 -0
- data/lib/pacecar/boolean.rb +34 -0
- data/lib/pacecar/datetime.rb +91 -0
- data/lib/pacecar/duration.rb +51 -0
- data/lib/pacecar/helpers.rb +79 -0
- data/lib/pacecar/limit.rb +22 -0
- data/lib/pacecar/numeric.rb +29 -0
- data/lib/pacecar/order.rb +24 -0
- data/lib/pacecar/polymorph.rb +18 -0
- data/lib/pacecar/presence.rb +23 -0
- data/lib/pacecar/ranking.rb +26 -0
- data/lib/pacecar/search.rb +47 -0
- data/lib/pacecar/state.rb +36 -0
- metadata +18 -4
data/lib/pacecar.rb
ADDED
@@ -0,0 +1,34 @@
|
|
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
|
+
require 'pacecar/numeric'
|
14
|
+
|
15
|
+
module Pacecar
|
16
|
+
def self.included(base)
|
17
|
+
base.class_eval do
|
18
|
+
include Pacecar::Associations
|
19
|
+
include Pacecar::Boolean
|
20
|
+
include Pacecar::Datetime
|
21
|
+
include Pacecar::Duration
|
22
|
+
include Pacecar::Limit
|
23
|
+
include Pacecar::Order
|
24
|
+
include Pacecar::Polymorph
|
25
|
+
include Pacecar::Presence
|
26
|
+
include Pacecar::Ranking
|
27
|
+
include Pacecar::Search
|
28
|
+
include Pacecar::State
|
29
|
+
include Pacecar::Numeric
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
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
|
+
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
|
+
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
|
+
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 #{connection.quote_table_name(name)} where #{connection.quote_table_name(name)}.#{connection.quote_column_name reflections[name].primary_key_name} = #{quoted_table_name}.#{connection.quote_column_name primary_key} and #{connection.quote_table_name(name)}.#{connection.quote_column_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
|
+
scope name.to_sym, :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} = ?", true]
|
18
|
+
scope "not_#{name}".to_sym, :conditions => ["#{quoted_table_name}.#{connection.quote_column_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,91 @@
|
|
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
|
+
scope "#{name}_before".to_sym, lambda { |time|
|
25
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} <= ?", time] }
|
26
|
+
}
|
27
|
+
scope "#{name}_after".to_sym, lambda { |time|
|
28
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} >= ?", time] }
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def define_past_future_scopes(name)
|
33
|
+
scope "#{name}_in_past", lambda {
|
34
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} <= ?", now] }
|
35
|
+
}
|
36
|
+
scope "#{name}_in_future", lambda {
|
37
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} >= ?", now] }
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def define_inside_outside_scopes(name)
|
42
|
+
scope "#{name}_inside".to_sym, lambda { |start, stop|
|
43
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} >= ? and #{quoted_table_name}.#{connection.quote_column_name name} <= ?", start, stop] }
|
44
|
+
}
|
45
|
+
scope "#{name}_outside".to_sym, lambda { |start, stop|
|
46
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} <= ? or #{quoted_table_name}.#{connection.quote_column_name name} >= ?", start, stop] }
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def define_in_date_scopes(name)
|
51
|
+
case connection.adapter_name
|
52
|
+
when 'MySQL', 'Mysql2'
|
53
|
+
scope "#{name}_in_year".to_sym, lambda { |year|
|
54
|
+
{ :conditions => ["year(#{quoted_table_name}.#{connection.quote_column_name name}) = ?", year.to_i] }
|
55
|
+
}
|
56
|
+
scope "#{name}_in_month".to_sym, lambda { |month|
|
57
|
+
{ :conditions => ["month(#{quoted_table_name}.#{connection.quote_column_name name}) = ?", month.to_i] }
|
58
|
+
}
|
59
|
+
scope "#{name}_in_day".to_sym, lambda { |day|
|
60
|
+
{ :conditions => ["day(#{quoted_table_name}.#{connection.quote_column_name name}) = ?", day.to_i] }
|
61
|
+
}
|
62
|
+
when 'PostgreSQL'
|
63
|
+
scope "#{name}_in_year".to_sym, lambda { |year|
|
64
|
+
{ :conditions => ["extract(year from #{quoted_table_name}.#{connection.quote_column_name name}) = ?", year.to_i] }
|
65
|
+
}
|
66
|
+
scope "#{name}_in_month".to_sym, lambda { |month|
|
67
|
+
{ :conditions => ["extract(month from #{quoted_table_name}.#{connection.quote_column_name name}) = ?", month.to_i] }
|
68
|
+
}
|
69
|
+
scope "#{name}_in_day".to_sym, lambda { |day|
|
70
|
+
{ :conditions => ["extract(day from #{quoted_table_name}.#{connection.quote_column_name name}) = ?", day.to_i] }
|
71
|
+
}
|
72
|
+
when 'SQLite'
|
73
|
+
scope "#{name}_in_year".to_sym, lambda { |year|
|
74
|
+
{ :conditions => ["strftime('%Y', #{quoted_table_name}.#{connection.quote_column_name name}) = ?", sprintf('%04d', year)] }
|
75
|
+
}
|
76
|
+
scope "#{name}_in_month".to_sym, lambda { |month|
|
77
|
+
{ :conditions => ["strftime('%m', #{quoted_table_name}.#{connection.quote_column_name name}) = ?", sprintf('%02d', month)] }
|
78
|
+
}
|
79
|
+
scope "#{name}_in_day".to_sym, lambda { |day|
|
80
|
+
{ :conditions => ["strftime('%d', #{quoted_table_name}.#{connection.quote_column_name name}) = ?", sprintf('%02d', day)] }
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def now
|
86
|
+
defined?(Time.zone_default) && Time.zone_default ? Time.zone_default.now : Time.now
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,51 @@
|
|
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
|
+
case connection.adapter_name
|
16
|
+
when 'MySQL', 'Mysql2'
|
17
|
+
scope :with_duration_of, lambda { |duration, start, stop|
|
18
|
+
{ :conditions => ["abs(datediff(#{quoted_table_name}.#{connection.quote_column_name start}, #{quoted_table_name}.#{connection.quote_column_name stop})) = ?", duration] }
|
19
|
+
}
|
20
|
+
scope :with_duration_over, lambda { |duration, start, stop|
|
21
|
+
{ :conditions => ["abs(datediff(#{quoted_table_name}.#{connection.quote_column_name start}, #{quoted_table_name}.#{connection.quote_column_name stop})) > ?", duration] }
|
22
|
+
}
|
23
|
+
scope :with_duration_under, lambda { |duration, start, stop|
|
24
|
+
{ :conditions => ["abs(datediff(#{quoted_table_name}.#{connection.quote_column_name start}, #{quoted_table_name}.#{connection.quote_column_name stop})) < ?", duration] }
|
25
|
+
}
|
26
|
+
when 'PostgreSQL'
|
27
|
+
scope :with_duration_of, lambda { |duration, start, stop|
|
28
|
+
{ :conditions => ["age(#{quoted_table_name}.#{connection.quote_column_name stop}, #{quoted_table_name}.#{connection.quote_column_name start}) = '? days'", duration] }
|
29
|
+
}
|
30
|
+
scope :with_duration_over, lambda { |duration, start, stop|
|
31
|
+
{ :conditions => ["age(#{quoted_table_name}.#{connection.quote_column_name stop}, #{quoted_table_name}.#{connection.quote_column_name start}) > interval '? days'", duration] }
|
32
|
+
}
|
33
|
+
scope :with_duration_under, lambda { |duration, start, stop|
|
34
|
+
{ :conditions => ["age(#{quoted_table_name}.#{connection.quote_column_name stop}, #{quoted_table_name}.#{connection.quote_column_name start}) < interval '? days'", duration] }
|
35
|
+
}
|
36
|
+
when 'SQLite'
|
37
|
+
scope :with_duration_of, lambda { |duration, start, stop|
|
38
|
+
{ :conditions => ["abs(julianday(#{quoted_table_name}.#{connection.quote_column_name start}) - julianday(#{quoted_table_name}.#{connection.quote_column_name stop})) = ?", duration] }
|
39
|
+
}
|
40
|
+
scope :with_duration_over, lambda { |duration, start, stop|
|
41
|
+
{ :conditions => ["abs(julianday(#{quoted_table_name}.#{connection.quote_column_name start}) - julianday(#{quoted_table_name}.#{connection.quote_column_name stop})) > ?", duration] }
|
42
|
+
}
|
43
|
+
scope :with_duration_under, lambda { |duration, start, stop|
|
44
|
+
{ :conditions => ["abs(julianday(#{quoted_table_name}.#{connection.quote_column_name start}) - julianday(#{quoted_table_name}.#{connection.quote_column_name stop})) < ?", duration] }
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,79 @@
|
|
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_column_names
|
17
|
+
safe_columns.collect(&:name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def non_boolean_column_names
|
21
|
+
column_names_without_type :boolean
|
22
|
+
end
|
23
|
+
|
24
|
+
def boolean_column_names
|
25
|
+
column_names_for_type :boolean
|
26
|
+
end
|
27
|
+
|
28
|
+
def datetime_column_names
|
29
|
+
column_names_for_type :datetime, :date
|
30
|
+
end
|
31
|
+
|
32
|
+
def text_and_string_column_names
|
33
|
+
column_names_for_type :text, :string
|
34
|
+
end
|
35
|
+
|
36
|
+
def non_state_text_and_string_columns
|
37
|
+
text_and_string_column_names.reject { |name| name =~ Pacecar::Helpers.options[:state_pattern] }
|
38
|
+
end
|
39
|
+
|
40
|
+
def numeric_column_names
|
41
|
+
column_names_for_type :integer, :float
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def safe_columns
|
47
|
+
case ActiveRecord::Base.connection.adapter_name
|
48
|
+
when 'MySQL'
|
49
|
+
begin
|
50
|
+
columns
|
51
|
+
rescue Mysql::Error
|
52
|
+
Array.new
|
53
|
+
end
|
54
|
+
when 'Mysql2'
|
55
|
+
begin
|
56
|
+
columns
|
57
|
+
rescue Mysql2::Error
|
58
|
+
Array.new
|
59
|
+
end
|
60
|
+
when 'SQLite', 'PostgreSQL'
|
61
|
+
begin
|
62
|
+
columns
|
63
|
+
rescue ActiveRecord::StatementInvalid # If the table does not exist
|
64
|
+
Array.new
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def column_names_for_type(*types)
|
70
|
+
safe_columns.select { |column| types.include? column.type }.collect(&:name)
|
71
|
+
end
|
72
|
+
|
73
|
+
def column_names_without_type(*types)
|
74
|
+
safe_columns.select { |column| ! types.include? column.type }.collect(&:name)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
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
|
+
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,29 @@
|
|
1
|
+
module Pacecar
|
2
|
+
module Numeric
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def self.extended(base)
|
9
|
+
base.send :define_numeric_scopes
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def define_numeric_scopes
|
15
|
+
numeric_column_names.each do |name|
|
16
|
+
{ :greater_than => '>', :less_than => '<' }.each do |method_name, symbol|
|
17
|
+
scope "#{name}_#{method_name}".to_sym, lambda { |value|
|
18
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} #{symbol} ?", value] }
|
19
|
+
}
|
20
|
+
scope "#{name}_#{method_name}_or_equal_to".to_sym, lambda { |value|
|
21
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} #{symbol}= ?", value] }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
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_column_names.each do |name|
|
16
|
+
scope "by_#{name}".to_sym, lambda { |*args|
|
17
|
+
{ :order => "#{quoted_table_name}.#{connection.quote_column_name name} #{args.flatten.first || 'asc'}" }
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
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
|
+
scope "for_#{name}_type".to_sym, lambda { |type|
|
11
|
+
polymorph_type = "#{name}_type"
|
12
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name polymorph_type} = ?", type.to_s] }
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
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
|
+
non_boolean_column_names.each do |name|
|
16
|
+
scope "#{name}_present".to_sym, :conditions => "#{quoted_table_name}.#{connection.quote_column_name name} IS NOT NULL"
|
17
|
+
scope "#{name}_missing".to_sym, :conditions => "#{quoted_table_name}.#{connection.quote_column_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
|
+
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}"
|
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
|
+
scope "#{name}_equals".to_sym, lambda { |query|
|
18
|
+
{ :conditions => { table_name => { name.to_sym => query} } }
|
19
|
+
}
|
20
|
+
end
|
21
|
+
text_and_string_column_names.each do |name|
|
22
|
+
scope "#{name}_matches".to_sym, lambda { |query|
|
23
|
+
{ :conditions => ["lower(#{quoted_table_name}.#{connection.quote_column_name(name)}) LIKE lower(:query)", { :query => "%#{query}%" }] }
|
24
|
+
}
|
25
|
+
scope "#{name}_starts_with".to_sym, lambda { |query|
|
26
|
+
{ :conditions => ["lower(#{quoted_table_name}.#{connection.quote_column_name(name)}) LIKE lower(:query)", { :query => "#{query}%" }] }
|
27
|
+
}
|
28
|
+
scope "#{name}_ends_with".to_sym, lambda { |query|
|
29
|
+
{ :conditions => ["lower(#{quoted_table_name}.#{connection.quote_column_name(name)}) LIKE lower(:query)", { :query => "%#{query}" }] }
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def define_basic_search_scope
|
35
|
+
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| "lower(#{quoted_table_name}.#{connection.quote_column_name(name)}) LIKE lower(: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
|
+
scope "#{name}_#{state.downcase}".to_sym, :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} = ?", state]
|
15
|
+
scope "#{name}_not_#{state.downcase}".to_sym, :conditions => ["#{quoted_table_name}.#{connection.quote_column_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
|
+
scope "#{name}".to_sym, lambda { |state|
|
26
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} = ?", state] }
|
27
|
+
}
|
28
|
+
scope "#{name}_not".to_sym, lambda { |state|
|
29
|
+
{ :conditions => ["#{quoted_table_name}.#{connection.quote_column_name name} <> ?", state] }
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pacecar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 1.4.
|
9
|
+
- 4
|
10
|
+
version: 1.4.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Jankowski
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-11 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -31,6 +31,20 @@ files:
|
|
31
31
|
- init.rb
|
32
32
|
- README.rdoc
|
33
33
|
- MIT-LICENSE
|
34
|
+
- lib/pacecar/associations.rb
|
35
|
+
- lib/pacecar/boolean.rb
|
36
|
+
- lib/pacecar/datetime.rb
|
37
|
+
- lib/pacecar/duration.rb
|
38
|
+
- lib/pacecar/helpers.rb
|
39
|
+
- lib/pacecar/limit.rb
|
40
|
+
- lib/pacecar/numeric.rb
|
41
|
+
- lib/pacecar/order.rb
|
42
|
+
- lib/pacecar/polymorph.rb
|
43
|
+
- lib/pacecar/presence.rb
|
44
|
+
- lib/pacecar/ranking.rb
|
45
|
+
- lib/pacecar/search.rb
|
46
|
+
- lib/pacecar/state.rb
|
47
|
+
- lib/pacecar.rb
|
34
48
|
has_rdoc: true
|
35
49
|
homepage: http://github.com/thoughtbot/pacecar
|
36
50
|
licenses: []
|