cohort_analysis 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.'
|