cohort_scope 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/cohort_scope.gemspec +10 -2
- data/lib/cohort_scope.rb +9 -124
- data/lib/cohort_scope/big_cohort.rb +21 -0
- data/lib/cohort_scope/cohort.rb +81 -0
- data/lib/cohort_scope/strict_cohort.rb +13 -0
- data/test/helper.rb +40 -4
- data/test/test_cohort.rb +44 -0
- data/test/test_cohort_scope.rb +6 -13
- metadata +23 -4
data/Rakefile
CHANGED
@@ -13,7 +13,7 @@ begin
|
|
13
13
|
gem.add_dependency "activesupport", ">=3.0.0.beta4"
|
14
14
|
gem.add_dependency "activerecord", ">=3.0.0.beta4"
|
15
15
|
gem.add_development_dependency "shoulda", ">= 2.10.3"
|
16
|
-
|
16
|
+
gem.add_development_dependency 'sqlite3-ruby'
|
17
17
|
end
|
18
18
|
Jeweler::GemcutterTasks.new
|
19
19
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/cohort_scope.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cohort_scope}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Seamus Abshere", "Andy Rossmeissl", "Derek Kastner"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-10-15}
|
13
13
|
s.description = %q{Provides big_cohort, which widens by finding the constraint that eliminates the most records and removing it. Also provides strict_cohort, which widens by eliminating constraints in order.}
|
14
14
|
s.email = %q{seamus@abshere.net}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,7 +25,11 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"cohort_scope.gemspec",
|
27
27
|
"lib/cohort_scope.rb",
|
28
|
+
"lib/cohort_scope/big_cohort.rb",
|
29
|
+
"lib/cohort_scope/cohort.rb",
|
30
|
+
"lib/cohort_scope/strict_cohort.rb",
|
28
31
|
"test/helper.rb",
|
32
|
+
"test/test_cohort.rb",
|
29
33
|
"test/test_cohort_scope.rb"
|
30
34
|
]
|
31
35
|
s.homepage = %q{http://github.com/seamusabshere/cohort_scope}
|
@@ -35,6 +39,7 @@ Gem::Specification.new do |s|
|
|
35
39
|
s.summary = %q{Provides cohorts (in the form of ActiveRecord scopes) that dynamically widen until they contain a certain number of records.}
|
36
40
|
s.test_files = [
|
37
41
|
"test/helper.rb",
|
42
|
+
"test/test_cohort.rb",
|
38
43
|
"test/test_cohort_scope.rb"
|
39
44
|
]
|
40
45
|
|
@@ -46,15 +51,18 @@ Gem::Specification.new do |s|
|
|
46
51
|
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0.beta4"])
|
47
52
|
s.add_runtime_dependency(%q<activerecord>, [">= 3.0.0.beta4"])
|
48
53
|
s.add_development_dependency(%q<shoulda>, [">= 2.10.3"])
|
54
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
49
55
|
else
|
50
56
|
s.add_dependency(%q<activesupport>, [">= 3.0.0.beta4"])
|
51
57
|
s.add_dependency(%q<activerecord>, [">= 3.0.0.beta4"])
|
52
58
|
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
59
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
53
60
|
end
|
54
61
|
else
|
55
62
|
s.add_dependency(%q<activesupport>, [">= 3.0.0.beta4"])
|
56
63
|
s.add_dependency(%q<activerecord>, [">= 3.0.0.beta4"])
|
57
64
|
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
65
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
data/lib/cohort_scope.rb
CHANGED
@@ -1,28 +1,12 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'active_support'
|
3
3
|
require 'active_support/version'
|
4
|
-
%w{
|
5
|
-
active_support/core_ext/module/delegation
|
6
|
-
}.each do |active_support_3_requirement|
|
7
|
-
require active_support_3_requirement
|
8
|
-
end if ActiveSupport::VERSION::MAJOR == 3
|
9
4
|
|
10
|
-
module
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def inspect_count_only?
|
16
|
-
@inspect_count_only == true
|
17
|
-
end
|
18
|
-
def as_json(*)
|
19
|
-
inspect_count_only? ? { :members => count } : super
|
20
|
-
end
|
21
|
-
def inspect
|
22
|
-
inspect_count_only? ? "<Massive ActiveRecord scope with #{count} members>" : super
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
5
|
+
require 'active_support/core_ext/module/delegation' if ActiveSupport::VERSION::MAJOR == 3
|
6
|
+
|
7
|
+
require 'cohort_scope/cohort'
|
8
|
+
require 'cohort_scope/big_cohort'
|
9
|
+
require 'cohort_scope/strict_cohort'
|
26
10
|
|
27
11
|
module CohortScope
|
28
12
|
def self.extended(klass)
|
@@ -31,9 +15,9 @@ module CohortScope
|
|
31
15
|
|
32
16
|
# Find the biggest scope possible by removing constraints <b>in any order</b>.
|
33
17
|
# Returns an empty scope if it can't meet the minimum scope size.
|
34
|
-
def big_cohort(constraints = {}, custom_minimum_cohort_size =
|
18
|
+
def big_cohort(constraints = {}, custom_minimum_cohort_size = self.minimum_cohort_size)
|
35
19
|
raise ArgumentError, "You can't give a big_cohort an OrderedHash; do you want strict_cohort?" if constraints.is_a?(ActiveSupport::OrderedHash)
|
36
|
-
|
20
|
+
BigCohort.create self, constraints, custom_minimum_cohort_size
|
37
21
|
end
|
38
22
|
|
39
23
|
# Find the first acceptable scope by removing constraints <b>in strict order</b>, starting with the last constraint.
|
@@ -52,107 +36,8 @@ module CohortScope
|
|
52
36
|
#
|
53
37
|
# If the original constraints don't meet the minimum scope size, then the only constraint that can be removed is birthdate.
|
54
38
|
# In other words, this would never return a scope that was constrained on birthdate but not on favorite_color.
|
55
|
-
def strict_cohort(constraints, custom_minimum_cohort_size =
|
39
|
+
def strict_cohort(constraints, custom_minimum_cohort_size = self.minimum_cohort_size)
|
56
40
|
raise ArgumentError, "You need to give strict_cohort an OrderedHash" unless constraints.is_a?(ActiveSupport::OrderedHash)
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
protected
|
61
|
-
|
62
|
-
# Recursively look for a scope that meets the constraints and is at least <tt>minimum_cohort_size</tt>.
|
63
|
-
def _cohort_scope(constraints, custom_minimum_cohort_size)
|
64
|
-
raise RuntimeError, "You need to set #{name}.minimum_cohort_size = X" unless minimum_cohort_size.present?
|
65
|
-
|
66
|
-
if constraints.values.none? # failing base case
|
67
|
-
empty_cohort = scoped.where '1 = 2'
|
68
|
-
empty_cohort.inspect_count_only!
|
69
|
-
return empty_cohort
|
70
|
-
end
|
71
|
-
|
72
|
-
this_hash = _cohort_constraints constraints
|
73
|
-
this_count = scoped.where(this_hash).count
|
74
|
-
|
75
|
-
if this_count >= (custom_minimum_cohort_size || minimum_cohort_size) # successful base case
|
76
|
-
cohort = scoped.where this_hash
|
77
|
-
else
|
78
|
-
cohort = _cohort_scope _cohort_reduce_constraints(constraints), custom_minimum_cohort_size
|
79
|
-
end
|
80
|
-
cohort.inspect_count_only!
|
81
|
-
cohort
|
82
|
-
end
|
83
|
-
|
84
|
-
# Sanitize constraints by
|
85
|
-
# * removing nil constraints (so constraints like "X IS NULL" are impossible, sorry)
|
86
|
-
# * converting ActiveRecord::Base objects into integer foreign key constraints
|
87
|
-
def _cohort_constraints(constraints)
|
88
|
-
new_hash = constraints.is_a?(ActiveSupport::OrderedHash) ? ActiveSupport::OrderedHash.new : Hash.new
|
89
|
-
conditions = constraints.inject(new_hash) do |memo, tuple|
|
90
|
-
k, v = tuple
|
91
|
-
if v.kind_of?(ActiveRecord::Base)
|
92
|
-
condition = { _cohort_association_primary_key(k) => v.to_param }
|
93
|
-
elsif !v.nil?
|
94
|
-
condition = { k => v }
|
95
|
-
end
|
96
|
-
memo.merge! condition if condition.is_a? Hash
|
97
|
-
memo
|
98
|
-
end
|
99
|
-
conditions
|
100
|
-
end
|
101
|
-
|
102
|
-
# Convert constraints that are provided as ActiveRecord::Base objects into their corresponding integer primary keys.
|
103
|
-
#
|
104
|
-
# Only works for <tt>belongs_to</tt> relationships.
|
105
|
-
#
|
106
|
-
# For example, :car => <#Car> might get translated into :car_id => 44.
|
107
|
-
def _cohort_association_primary_key(name)
|
108
|
-
@_cohort_association_primary_keys ||= {}
|
109
|
-
return @_cohort_association_primary_keys[name] if @_cohort_association_primary_keys.has_key? name
|
110
|
-
a = reflect_on_association name
|
111
|
-
raise "can't use cohort scope on :through associations (#{self.name} #{name})" if a.options.has_key? :through
|
112
|
-
if !a.primary_key_name.blank?
|
113
|
-
@_cohort_association_primary_keys[name] = a.primary_key_name
|
114
|
-
else
|
115
|
-
raise "we need some other way to find primary key"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Choose how to reduce constraints based on whether we're looking for a big cohort or a strict cohort.
|
120
|
-
def _cohort_reduce_constraints(constraints)
|
121
|
-
case constraints
|
122
|
-
when ActiveSupport::OrderedHash
|
123
|
-
_cohort_reduce_constraints_in_order constraints
|
124
|
-
when Hash
|
125
|
-
_cohort_reduce_constraints_seeking_maximum_count constraints
|
126
|
-
else
|
127
|
-
raise "what did you pass me? #{constraints}"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# (Used by <tt>big_cohort</tt>)
|
132
|
-
#
|
133
|
-
# Reduce constraints by removing them one by one and counting the results.
|
134
|
-
#
|
135
|
-
# The constraint whose removal leads to the highest record count is removed from the overall constraint set.
|
136
|
-
def _cohort_reduce_constraints_seeking_maximum_count(constraints)
|
137
|
-
highest_count_after_removal = nil
|
138
|
-
losing_key = nil
|
139
|
-
constraints.keys.each do |key|
|
140
|
-
test_constraints = constraints.except(key)
|
141
|
-
count_after_removal = scoped.where(_cohort_constraints(test_constraints)).count
|
142
|
-
if highest_count_after_removal.nil? or count_after_removal > highest_count_after_removal
|
143
|
-
highest_count_after_removal = count_after_removal
|
144
|
-
losing_key = key
|
145
|
-
end
|
146
|
-
end
|
147
|
-
constraints.except losing_key
|
148
|
-
end
|
149
|
-
|
150
|
-
# (Used by <tt>strict_cohort</tt>)
|
151
|
-
#
|
152
|
-
# Reduce constraints by removing the least important one.
|
153
|
-
def _cohort_reduce_constraints_in_order(constraints)
|
154
|
-
reduced_constraints = constraints.dup
|
155
|
-
reduced_constraints.delete constraints.keys.last
|
156
|
-
reduced_constraints
|
41
|
+
StrictCohort.create self, constraints, custom_minimum_cohort_size
|
157
42
|
end
|
158
43
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CohortScope
|
2
|
+
class BigCohort < Cohort
|
3
|
+
|
4
|
+
# Reduce constraints by removing them one by one and counting the results.
|
5
|
+
#
|
6
|
+
# The constraint whose removal leads to the highest record count is removed from the overall constraint set.
|
7
|
+
def self.reduce_constraints(model, constraints)
|
8
|
+
highest_count_after_removal = nil
|
9
|
+
losing_key = nil
|
10
|
+
constraints.keys.each do |key|
|
11
|
+
test_constraints = constraints.except(key)
|
12
|
+
count_after_removal = model.scoped.where(sanitize_constraints(model, test_constraints)).count
|
13
|
+
if highest_count_after_removal.nil? or count_after_removal > highest_count_after_removal
|
14
|
+
highest_count_after_removal = count_after_removal
|
15
|
+
losing_key = key
|
16
|
+
end
|
17
|
+
end
|
18
|
+
constraints.except losing_key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module CohortScope
|
4
|
+
class Cohort < Delegator
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# Recursively look for a scope that meets the constraints and is at least <tt>minimum_cohort_size</tt>.
|
8
|
+
def create(model, constraints, custom_minimum_cohort_size)
|
9
|
+
raise RuntimeError, "You need to set #{name}.minimum_cohort_size = X" unless model.minimum_cohort_size.present?
|
10
|
+
|
11
|
+
if constraints.values.none? # failing base case
|
12
|
+
empty_cohort = model.scoped.where '1 = 2'
|
13
|
+
return new(empty_cohort)
|
14
|
+
end
|
15
|
+
|
16
|
+
constraint_hash = sanitize_constraints model, constraints
|
17
|
+
constrained_scope = model.scoped.where(constraint_hash)
|
18
|
+
|
19
|
+
if constrained_scope.count >= custom_minimum_cohort_size
|
20
|
+
new constrained_scope
|
21
|
+
else
|
22
|
+
reduced_constraints = reduce_constraints(model, constraints)
|
23
|
+
create(model, reduced_constraints, custom_minimum_cohort_size)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sanitize constraints by
|
28
|
+
# * removing nil constraints (so constraints like "X IS NULL" are impossible, sorry)
|
29
|
+
# * converting ActiveRecord::Base objects into integer foreign key constraints
|
30
|
+
def sanitize_constraints(model, constraints)
|
31
|
+
new_hash = constraints.is_a?(ActiveSupport::OrderedHash) ? ActiveSupport::OrderedHash.new : Hash.new
|
32
|
+
conditions = constraints.inject(new_hash) do |memo, tuple|
|
33
|
+
k, v = tuple
|
34
|
+
if v.kind_of?(ActiveRecord::Base)
|
35
|
+
primary_key = association_primary_key(model, k)
|
36
|
+
param = v.respond_to?(primary_key) ? v.send(primary_key) : v.to_param
|
37
|
+
condition = { primary_key => param }
|
38
|
+
elsif !v.nil?
|
39
|
+
condition = { k => v }
|
40
|
+
end
|
41
|
+
memo.merge! condition if condition.is_a? Hash
|
42
|
+
memo
|
43
|
+
end
|
44
|
+
conditions
|
45
|
+
end
|
46
|
+
|
47
|
+
# Convert constraints that are provided as ActiveRecord::Base objects into their corresponding integer primary keys.
|
48
|
+
#
|
49
|
+
# Only works for <tt>belongs_to</tt> relationships.
|
50
|
+
#
|
51
|
+
# For example, :car => <#Car> might get translated into :car_id => 44.
|
52
|
+
def association_primary_key(model, name)
|
53
|
+
@_cohort_association_primary_keys ||= {}
|
54
|
+
return @_cohort_association_primary_keys[name] if @_cohort_association_primary_keys.has_key? name
|
55
|
+
a = model.reflect_on_association name
|
56
|
+
raise "there is no association #{name.inspect} on #{model}" if a.nil?
|
57
|
+
raise "can't use cohort scope on :through associations (#{self.name} #{name})" if a.options.has_key? :through
|
58
|
+
if !a.primary_key_name.blank?
|
59
|
+
@_cohort_association_primary_keys[name] = a.primary_key_name
|
60
|
+
else
|
61
|
+
raise "we need some other way to find primary key"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize(obj)
|
67
|
+
@_ch_obj = obj
|
68
|
+
end
|
69
|
+
def __getobj__
|
70
|
+
@_ch_obj
|
71
|
+
end
|
72
|
+
|
73
|
+
def as_json(*)
|
74
|
+
{ :members => count }
|
75
|
+
end
|
76
|
+
|
77
|
+
def inspect
|
78
|
+
"<Massive ActiveRecord scope with #{count} members>"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module CohortScope
|
2
|
+
class StrictCohort < Cohort
|
3
|
+
|
4
|
+
# (Used by <tt>strict_cohort</tt>)
|
5
|
+
#
|
6
|
+
# Reduce constraints by removing the least important one.
|
7
|
+
def self.reduce_constraints(model, constraints)
|
8
|
+
reduced_constraints = constraints.dup
|
9
|
+
reduced_constraints.delete constraints.keys.last
|
10
|
+
reduced_constraints
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/test/helper.rb
CHANGED
@@ -18,10 +18,8 @@ ActiveSupport::Notifications.subscribe do |*args|
|
|
18
18
|
end
|
19
19
|
|
20
20
|
ActiveRecord::Base.establish_connection(
|
21
|
-
'adapter' => '
|
22
|
-
'database' => '
|
23
|
-
'username' => 'root',
|
24
|
-
'password' => 'password'
|
21
|
+
'adapter' => 'sqlite3',
|
22
|
+
'database' => ':memory:'
|
25
23
|
)
|
26
24
|
|
27
25
|
ActiveRecord::Schema.define(:version => 20090819143429) do
|
@@ -30,6 +28,19 @@ ActiveRecord::Schema.define(:version => 20090819143429) do
|
|
30
28
|
t.string 'favorite_color'
|
31
29
|
t.integer 'teeth'
|
32
30
|
end
|
31
|
+
create_table 'houses', :force => true do |t|
|
32
|
+
t.string 'period'
|
33
|
+
t.string 'address'
|
34
|
+
t.integer 'storeys'
|
35
|
+
end
|
36
|
+
create_table 'styles', :force => true do |t|
|
37
|
+
t.string 'period'
|
38
|
+
t.string 'name'
|
39
|
+
end
|
40
|
+
create_table 'residents', :force => true do |t|
|
41
|
+
t.integer 'house_id'
|
42
|
+
t.string 'name'
|
43
|
+
end
|
33
44
|
end
|
34
45
|
|
35
46
|
class Citizen < ActiveRecord::Base
|
@@ -54,3 +65,28 @@ end
|
|
54
65
|
].each do |birthdate, favorite_color, teeth|
|
55
66
|
Citizen.create! :birthdate => birthdate, :favorite_color => favorite_color, :teeth => teeth
|
56
67
|
end
|
68
|
+
|
69
|
+
class Style < ActiveRecord::Base
|
70
|
+
extend CohortScope
|
71
|
+
self.minimum_cohort_size = 3
|
72
|
+
has_many :houses
|
73
|
+
end
|
74
|
+
class House < ActiveRecord::Base
|
75
|
+
belongs_to :style, :foreign_key => 'period', :primary_key => 'period'
|
76
|
+
has_one :resident
|
77
|
+
end
|
78
|
+
class Resident < ActiveRecord::Base
|
79
|
+
has_one :house
|
80
|
+
end
|
81
|
+
|
82
|
+
Style.create! :period => 'arts and crafts', :name => 'classical revival'
|
83
|
+
Style.create! :period => 'arts and crafts', :name => 'gothic'
|
84
|
+
Style.create! :period => 'arts and crafts', :name => 'art deco'
|
85
|
+
Style.create! :period => 'victorian', :name => 'stick-eastlake'
|
86
|
+
Style.create! :period => 'victorian', :name => 'queen anne'
|
87
|
+
h1 = House.create! :period => 'arts and crafts', :address => '123 Maple', :storeys => 1
|
88
|
+
h2 = House.create! :period => 'arts and crafts', :address => '223 Walnut', :storeys => 2
|
89
|
+
h3 = House.create! :period => 'victorian', :address => '323 Pine', :storeys => 2
|
90
|
+
Resident.create! :house => h1, :name => 'Bob'
|
91
|
+
Resident.create! :house => h2, :name => 'Rob'
|
92
|
+
Resident.create! :house => h3, :name => 'Gob'
|
data/test/test_cohort.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestCohortScope < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Citizen.minimum_cohort_size = 3
|
6
|
+
@date_range = (Date.parse('1980-01-01')..Date.parse('1990-01-01'))
|
7
|
+
end
|
8
|
+
|
9
|
+
def style
|
10
|
+
@style ||= Style.find_by_period 'arts and crafts'
|
11
|
+
end
|
12
|
+
|
13
|
+
context '.sanitize_constraints' do
|
14
|
+
should 'remove nil constraints' do
|
15
|
+
constraints = CohortScope::Cohort.sanitize_constraints Style, :eh => :tu, :bru => :te, :caesar => nil
|
16
|
+
assert_does_not_contain constraints.keys, :caesar
|
17
|
+
end
|
18
|
+
should 'keep normal constraints' do
|
19
|
+
constraints = CohortScope::Cohort.sanitize_constraints Style, :eh => :tu, :bru => :te, :caesar => nil
|
20
|
+
assert_equal :tu, constraints[:eh]
|
21
|
+
end
|
22
|
+
should 'include constraints that are models' do
|
23
|
+
gob = Resident.find_by_name 'Gob'
|
24
|
+
constraints = CohortScope::Cohort.sanitize_constraints House, :resident => gob
|
25
|
+
assert_equal gob.house_id, constraints[:house_id]
|
26
|
+
end
|
27
|
+
should 'include constraints that are models not related by primary key' do
|
28
|
+
constraints = CohortScope::Cohort.sanitize_constraints House, :style => style
|
29
|
+
assert_equal 'arts and crafts', constraints['period']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context '.association_primary_key' do
|
34
|
+
should 'include constraints that are models related by a primary key' do
|
35
|
+
gob = Resident.find_by_name('Gob')
|
36
|
+
key = CohortScope::Cohort.association_primary_key Resident, :house
|
37
|
+
assert_equal 'resident_id', key
|
38
|
+
end
|
39
|
+
should 'include constraints that are models related by a non-primary key' do
|
40
|
+
key = CohortScope::Cohort.association_primary_key House, :style
|
41
|
+
assert_equal 'period', key
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/test/test_cohort_scope.rb
CHANGED
@@ -26,6 +26,12 @@ class TestCohortScope < Test::Unit::TestCase
|
|
26
26
|
assert_equal "<Massive ActiveRecord scope with 9 members>", cohort.inspect
|
27
27
|
end
|
28
28
|
|
29
|
+
should "retain the scope's original behavior" do
|
30
|
+
cohort = Citizen.big_cohort :birthdate => @date_range, :favorite_color => 'heliotrope'
|
31
|
+
assert_kind_of Citizen, cohort.last
|
32
|
+
assert_kind_of Citizen, cohort.where(:teeth => 31).first
|
33
|
+
end
|
34
|
+
|
29
35
|
should "raise if no minimum_cohort_size is specified" do
|
30
36
|
Citizen.minimum_cohort_size = nil
|
31
37
|
assert_raises(RuntimeError) {
|
@@ -59,11 +65,6 @@ class TestCohortScope < Test::Unit::TestCase
|
|
59
65
|
Citizen.big_cohort ActiveSupport::OrderedHash.new
|
60
66
|
}
|
61
67
|
end
|
62
|
-
|
63
|
-
should "result in a relation that has inspect_count_only set" do
|
64
|
-
cohort = Citizen.big_cohort :favorite_color => 'heliotrope'
|
65
|
-
assert cohort.inspect_count_only?
|
66
|
-
end
|
67
68
|
end
|
68
69
|
|
69
70
|
context "strict_cohort" do
|
@@ -104,13 +105,5 @@ class TestCohortScope < Test::Unit::TestCase
|
|
104
105
|
cohort = Citizen.strict_cohort birthdate_matters_most
|
105
106
|
assert_equal 9, cohort.count
|
106
107
|
end
|
107
|
-
|
108
|
-
should "result in a relation that has inspect_count_only set" do
|
109
|
-
ordered_attributes = ActiveSupport::OrderedHash.new
|
110
|
-
ordered_attributes[:favorite_color] = 'heliotrope'
|
111
|
-
|
112
|
-
cohort = Citizen.strict_cohort ordered_attributes
|
113
|
-
assert cohort.inspect_count_only?
|
114
|
-
end
|
115
108
|
end
|
116
109
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cohort_scope
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.7
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Seamus Abshere
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2010-
|
20
|
+
date: 2010-10-15 00:00:00 -04:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -70,6 +70,20 @@ dependencies:
|
|
70
70
|
version: 2.10.3
|
71
71
|
type: :development
|
72
72
|
version_requirements: *id003
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: sqlite3-ruby
|
75
|
+
prerelease: false
|
76
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
type: :development
|
86
|
+
version_requirements: *id004
|
73
87
|
description: Provides big_cohort, which widens by finding the constraint that eliminates the most records and removing it. Also provides strict_cohort, which widens by eliminating constraints in order.
|
74
88
|
email: seamus@abshere.net
|
75
89
|
executables: []
|
@@ -88,7 +102,11 @@ files:
|
|
88
102
|
- VERSION
|
89
103
|
- cohort_scope.gemspec
|
90
104
|
- lib/cohort_scope.rb
|
105
|
+
- lib/cohort_scope/big_cohort.rb
|
106
|
+
- lib/cohort_scope/cohort.rb
|
107
|
+
- lib/cohort_scope/strict_cohort.rb
|
91
108
|
- test/helper.rb
|
109
|
+
- test/test_cohort.rb
|
92
110
|
- test/test_cohort_scope.rb
|
93
111
|
has_rdoc: true
|
94
112
|
homepage: http://github.com/seamusabshere/cohort_scope
|
@@ -126,4 +144,5 @@ specification_version: 3
|
|
126
144
|
summary: Provides cohorts (in the form of ActiveRecord scopes) that dynamically widen until they contain a certain number of records.
|
127
145
|
test_files:
|
128
146
|
- test/helper.rb
|
147
|
+
- test/test_cohort.rb
|
129
148
|
- test/test_cohort_scope.rb
|