cohort_analysis 1.0.0 → 1.0.1
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/CHANGELOG +7 -1
- data/Rakefile +11 -1
- data/cohort_analysis.gemspec +5 -0
- data/lib/cohort_analysis/strategy.rb +7 -4
- data/lib/cohort_analysis/version.rb +1 -1
- data/test/helper.rb +43 -1
- data/test/test_cohort_analysis.rb +15 -9
- metadata +33 -1
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
@@ -9,7 +9,17 @@ Rake::TestTask.new(:test) do |test|
|
|
9
9
|
test.verbose = true
|
10
10
|
end
|
11
11
|
|
12
|
-
task :
|
12
|
+
task :test_each_db_adapter do
|
13
|
+
%w{ mysql sqlite postgresql }.each do |database|
|
14
|
+
puts
|
15
|
+
puts "#{'*'*10} Running tests with #{database}"
|
16
|
+
puts
|
17
|
+
puts `rake test DATABASE=#{database}`
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
task :default => :test_each_db_adapter
|
22
|
+
task :spec => :test_each_db_adapter
|
13
23
|
|
14
24
|
require 'yard'
|
15
25
|
YARD::Rake::YardocTask.new
|
data/cohort_analysis.gemspec
CHANGED
@@ -30,9 +30,14 @@ Gem::Specification.new do |gem|
|
|
30
30
|
gem.add_development_dependency 'factory_girl', '~>2'
|
31
31
|
end
|
32
32
|
if RUBY_PLATFORM == 'java'
|
33
|
+
gem.add_development_dependency 'jruby-openssl'
|
33
34
|
gem.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
|
35
|
+
gem.add_development_dependency 'activerecord-jdbcmysql-adapter'
|
36
|
+
gem.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
|
34
37
|
else
|
35
38
|
gem.add_development_dependency 'sqlite3'
|
39
|
+
gem.add_development_dependency 'mysql2'
|
40
|
+
gem.add_development_dependency 'pg'
|
36
41
|
end
|
37
42
|
|
38
43
|
# gem.add_development_dependency 'debugger'
|
@@ -90,13 +90,16 @@ module CohortAnalysis
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
def other_constraints
|
94
|
+
select_manager.constraints.reject do |constraint|
|
95
|
+
self == constraint
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
93
99
|
def count(subset)
|
94
100
|
constraints = grasp subset
|
95
101
|
|
96
|
-
|
97
|
-
if self == constraint
|
98
|
-
next
|
99
|
-
end
|
102
|
+
other_constraints.each do |constraint|
|
100
103
|
if constraint.is_a? String
|
101
104
|
constraint = Arel::Nodes::Grouping.new constraint
|
102
105
|
end
|
data/test/helper.rb
CHANGED
@@ -14,6 +14,8 @@ require 'active_record_inline_schema'
|
|
14
14
|
|
15
15
|
require 'cohort_analysis'
|
16
16
|
|
17
|
+
require 'arel/nodes/table_alias' # strange
|
18
|
+
|
17
19
|
if ::Bundler.definition.specs['debugger'].first
|
18
20
|
require 'debugger'
|
19
21
|
elsif ::Bundler.definition.specs['ruby-debug'].first
|
@@ -23,7 +25,47 @@ end
|
|
23
25
|
# require 'logger'
|
24
26
|
# ActiveRecord::Base.logger = Logger.new($stdout)
|
25
27
|
|
26
|
-
|
28
|
+
case ENV['DATABASE']
|
29
|
+
when /mysql/i
|
30
|
+
bin = ENV['TEST_MYSQL_BIN'] || 'mysql'
|
31
|
+
username = ENV['TEST_MYSQL_USERNAME'] || 'root'
|
32
|
+
password = ENV['TEST_MYSQL_PASSWORD'] || 'password'
|
33
|
+
database = ENV['TEST_MYSQL_DATABASE'] || 'test_cohort_analysis'
|
34
|
+
cmd = "#{bin} -u #{username} -p#{password}"
|
35
|
+
`#{cmd} -e 'show databases'`
|
36
|
+
unless $?.success?
|
37
|
+
$stderr.puts "Skipping mysql tests because `#{cmd}` doesn't work"
|
38
|
+
exit 0
|
39
|
+
end
|
40
|
+
system %{#{cmd} -e "drop database #{database}"}
|
41
|
+
system %{#{cmd} -e "create database #{database}"}
|
42
|
+
ActiveRecord::Base.establish_connection(
|
43
|
+
'adapter' => (RUBY_PLATFORM == 'java' ? 'mysql' : 'mysql2'),
|
44
|
+
'encoding' => 'utf8',
|
45
|
+
'database' => database,
|
46
|
+
'username' => username,
|
47
|
+
'password' => password
|
48
|
+
)
|
49
|
+
when /postgr/i
|
50
|
+
createdb_bin = ENV['TEST_CREATEDB_BIN'] || 'createdb'
|
51
|
+
dropdb_bin = ENV['TEST_DROPDB_BIN'] || 'dropdb'
|
52
|
+
username = ENV['TEST_POSTGRES_USERNAME'] || `whoami`.chomp
|
53
|
+
# password = ENV['TEST_POSTGRES_PASSWORD'] || 'password'
|
54
|
+
database = ENV['TEST_POSTGRES_DATABASE'] || 'test_cohort_analysis'
|
55
|
+
system %{#{dropdb_bin} #{database}}
|
56
|
+
system %{#{createdb_bin} #{database}}
|
57
|
+
ActiveRecord::Base.establish_connection(
|
58
|
+
'adapter' => 'postgresql',
|
59
|
+
'encoding' => 'utf8',
|
60
|
+
'database' => database,
|
61
|
+
'username' => username
|
62
|
+
# 'password' => password
|
63
|
+
)
|
64
|
+
when /sqlite/i
|
65
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
66
|
+
else
|
67
|
+
raise "don't know how to test against #{ENV['DATABASE']}"
|
68
|
+
end
|
27
69
|
|
28
70
|
Arel::Table.engine = ActiveRecord::Base
|
29
71
|
|
@@ -183,7 +183,7 @@ shared_examples_for 'an adapter the provides #cohort' do
|
|
183
183
|
it "can get where sql" do
|
184
184
|
FactoryGirl.create(:lax_ord)
|
185
185
|
FactoryGirl.create(:lax_sfo)
|
186
|
-
model.cohort(:origin => 'LAX').where_sql.must_equal %{WHERE (
|
186
|
+
model.cohort(:origin => 'LAX').where_sql.delete('"`').must_equal %{WHERE (flights.origin = 'LAX')}
|
187
187
|
end
|
188
188
|
|
189
189
|
it "will resolve independently from other cohorts" do
|
@@ -230,31 +230,35 @@ shared_examples_for 'an adapter the provides #cohort' do
|
|
230
230
|
|
231
231
|
# sanity check!
|
232
232
|
it "has tests that use unions properly" do
|
233
|
-
ord = model.where(f_t[:dest].eq('ORD'))
|
234
|
-
sfo = model.where(f_t[:dest].eq('SFO'))
|
235
|
-
|
233
|
+
ord = model.where(f_t[:dest].eq('ORD'))
|
234
|
+
sfo = model.where(f_t[:dest].eq('SFO'))
|
235
|
+
ord.projections = [Arel.star]
|
236
|
+
sfo.projections = [Arel.star]
|
237
|
+
Flight.find_by_sql("SELECT * FROM #{Arel::Nodes::TableAlias.new(ord.union(sfo), 't1').to_sql}").must_equal [@ord, @sfo]
|
236
238
|
end
|
237
239
|
|
238
240
|
it "builds successful cohorts" do
|
239
241
|
ord = model.cohort(:dest => 'ORD').project(Arel.star)
|
240
242
|
sfo = model.cohort(:dest => 'SFO').project(Arel.star)
|
241
|
-
Flight.find_by_sql("SELECT * FROM #{ord.union(sfo).to_sql}").must_equal [@ord, @sfo]
|
243
|
+
Flight.find_by_sql("SELECT * FROM #{Arel::Nodes::TableAlias.new(ord.union(sfo), 't1').to_sql}").must_equal [@ord, @sfo]
|
242
244
|
|
243
245
|
msn = model.cohort(:origin => 'LAX', :dest => 'MSN').project(Arel.star)
|
244
246
|
lhr = model.cohort(:origin => 'LAX', :dest => 'LHR').project(Arel.star)
|
245
|
-
Flight.find_by_sql("SELECT * FROM #{msn.union(lhr).to_sql}").must_equal [@ord, @sfo]
|
247
|
+
Flight.find_by_sql("SELECT * FROM #{Arel::Nodes::TableAlias.new(msn.union(lhr), 't1').to_sql}").must_equal [@ord, @sfo]
|
246
248
|
end
|
247
249
|
|
248
250
|
it "doesn't somehow create unions with false positives" do
|
249
251
|
msn = model.cohort(:dest => 'MSN').project(Arel.star)
|
250
252
|
lhr = model.cohort(:dest => 'LHR').project(Arel.star)
|
251
|
-
ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM #{msn.union(lhr).to_sql}")
|
253
|
+
count = ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM #{Arel::Nodes::TableAlias.new(msn.union(lhr), 't1').to_sql}")
|
254
|
+
flunk "count was nil" if count.nil?
|
255
|
+
count.to_i.must_equal 0
|
252
256
|
end
|
253
257
|
|
254
258
|
it "builds unions where only one side has rows" do
|
255
259
|
msn = model.cohort(:dest => 'MSN').project(Arel.star)
|
256
260
|
ord = model.cohort(:dest => 'ORD').project(Arel.star)
|
257
|
-
Flight.find_by_sql("SELECT * FROM #{msn.union(ord).to_sql}").must_equal [@ord]
|
261
|
+
Flight.find_by_sql("SELECT * FROM #{Arel::Nodes::TableAlias.new(msn.union(ord), 't1').to_sql}").must_equal [@ord]
|
258
262
|
end
|
259
263
|
end
|
260
264
|
end
|
@@ -265,7 +269,9 @@ describe CohortAnalysis do
|
|
265
269
|
relation = relation.clone
|
266
270
|
relation.projections = [Arel.sql('COUNT(*)')]
|
267
271
|
sql = relation.to_sql
|
268
|
-
ActiveRecord::Base.connection.select_value(sql)
|
272
|
+
count = ActiveRecord::Base.connection.select_value(sql)
|
273
|
+
flunk "count was nil" if count.nil?
|
274
|
+
count.to_i.must_equal expected_count
|
269
275
|
end
|
270
276
|
|
271
277
|
def assert_members(expected_members, relation)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cohort_analysis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -158,6 +158,38 @@ dependencies:
|
|
158
158
|
- - ! '>='
|
159
159
|
- !ruby/object:Gem::Version
|
160
160
|
version: '0'
|
161
|
+
- !ruby/object:Gem::Dependency
|
162
|
+
name: mysql2
|
163
|
+
requirement: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
type: :development
|
170
|
+
prerelease: false
|
171
|
+
version_requirements: !ruby/object:Gem::Requirement
|
172
|
+
none: false
|
173
|
+
requirements:
|
174
|
+
- - ! '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
- !ruby/object:Gem::Dependency
|
178
|
+
name: pg
|
179
|
+
requirement: !ruby/object:Gem::Requirement
|
180
|
+
none: false
|
181
|
+
requirements:
|
182
|
+
- - ! '>='
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '0'
|
185
|
+
type: :development
|
186
|
+
prerelease: false
|
187
|
+
version_requirements: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ! '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
161
193
|
description: ! 'Lets you do cohort analysis based on two strategies: "big", which
|
162
194
|
discards characteristics for the maximum cohort result, and "strict", which discards
|
163
195
|
characteristics in order until a minimum cohort size is reached.'
|