split 3.4.1 → 4.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.rubocop.yml +177 -1
  4. data/.rubocop_todo.yml +40 -493
  5. data/.travis.yml +14 -42
  6. data/CHANGELOG.md +35 -0
  7. data/Gemfile +1 -0
  8. data/README.md +19 -1
  9. data/Rakefile +1 -0
  10. data/lib/split.rb +8 -2
  11. data/lib/split/algorithms/block_randomization.rb +1 -0
  12. data/lib/split/algorithms/weighted_sample.rb +2 -1
  13. data/lib/split/algorithms/whiplash.rb +3 -2
  14. data/lib/split/alternative.rb +1 -0
  15. data/lib/split/cache.rb +28 -0
  16. data/lib/split/combined_experiments_helper.rb +1 -0
  17. data/lib/split/configuration.rb +6 -12
  18. data/lib/split/dashboard.rb +17 -2
  19. data/lib/split/dashboard/helpers.rb +1 -0
  20. data/lib/split/dashboard/pagination_helpers.rb +1 -0
  21. data/lib/split/dashboard/paginator.rb +1 -0
  22. data/lib/split/dashboard/public/dashboard.js +10 -0
  23. data/lib/split/dashboard/public/style.css +5 -0
  24. data/lib/split/dashboard/views/_controls.erb +13 -0
  25. data/lib/split/encapsulated_helper.rb +3 -2
  26. data/lib/split/engine.rb +1 -0
  27. data/lib/split/exceptions.rb +1 -0
  28. data/lib/split/experiment.rb +81 -59
  29. data/lib/split/experiment_catalog.rb +1 -3
  30. data/lib/split/extensions/string.rb +1 -0
  31. data/lib/split/goals_collection.rb +1 -0
  32. data/lib/split/helper.rb +26 -7
  33. data/lib/split/metric.rb +2 -1
  34. data/lib/split/persistence.rb +4 -2
  35. data/lib/split/persistence/cookie_adapter.rb +1 -0
  36. data/lib/split/persistence/redis_adapter.rb +5 -0
  37. data/lib/split/persistence/session_adapter.rb +1 -0
  38. data/lib/split/redis_interface.rb +8 -28
  39. data/lib/split/trial.rb +20 -10
  40. data/lib/split/user.rb +14 -2
  41. data/lib/split/version.rb +2 -4
  42. data/lib/split/zscore.rb +1 -0
  43. data/spec/alternative_spec.rb +1 -1
  44. data/spec/cache_spec.rb +88 -0
  45. data/spec/configuration_spec.rb +1 -14
  46. data/spec/dashboard_spec.rb +45 -5
  47. data/spec/encapsulated_helper_spec.rb +1 -1
  48. data/spec/experiment_spec.rb +78 -7
  49. data/spec/goals_collection_spec.rb +1 -1
  50. data/spec/helper_spec.rb +68 -32
  51. data/spec/persistence/cookie_adapter_spec.rb +1 -1
  52. data/spec/persistence/redis_adapter_spec.rb +9 -0
  53. data/spec/redis_interface_spec.rb +0 -69
  54. data/spec/spec_helper.rb +5 -6
  55. data/spec/trial_spec.rb +45 -19
  56. data/spec/user_spec.rb +17 -0
  57. data/split.gemspec +7 -7
  58. metadata +23 -34
  59. data/gemfiles/4.2.gemfile +0 -9
@@ -48,7 +48,7 @@ describe Split::GoalsCollection do
48
48
  goals_collection.save
49
49
 
50
50
  goals_collection.delete
51
- expect(Split.redis.exists(goals_key)).to be false
51
+ expect(Split.redis.exists?(goals_key)).to be false
52
52
  end
53
53
  end
54
54
 
@@ -229,13 +229,15 @@ describe Split::Helper do
229
229
 
230
230
  context "when user already has experiment" do
231
231
  let(:mock_user){ Split::User.new(self, {'test_0' => 'test-alt'}) }
232
- before{
232
+
233
+ before do
233
234
  Split.configure do |config|
234
235
  config.allow_multiple_experiments = 'control'
235
236
  end
237
+
236
238
  Split::ExperimentCatalog.find_or_initialize('test_0', 'control', 'test-alt').save
237
239
  Split::ExperimentCatalog.find_or_initialize('test_1', 'control', 'test-alt').save
238
- }
240
+ end
239
241
 
240
242
  it "should restore previously selected alternative" do
241
243
  expect(ab_user.active_experiments.size).to eq 1
@@ -243,6 +245,16 @@ describe Split::Helper do
243
245
  expect(ab_test(:test_0, {'control' => 1}, {"test-alt" => 100})).to eq 'test-alt'
244
246
  end
245
247
 
248
+ it "should select the correct alternatives after experiment resets" do
249
+ experiment = Split::ExperimentCatalog.find(:test_0)
250
+ experiment.reset
251
+ mock_user[experiment.key] = 'test-alt'
252
+
253
+ expect(ab_user.active_experiments.size).to eq 1
254
+ expect(ab_test(:test_0, {'control' => 100}, {"test-alt" => 1})).to eq 'test-alt'
255
+ expect(ab_test(:test_0, {'control' => 0}, {"test-alt" => 100})).to eq 'test-alt'
256
+ end
257
+
246
258
  it "lets override existing choice" do
247
259
  pending "this requires user store reset on first call not depending on whelther it is current trial"
248
260
  @params = { 'ab_test' => { 'test_1' => 'test-alt' } }
@@ -265,33 +277,63 @@ describe Split::Helper do
265
277
  end
266
278
 
267
279
  describe 'metadata' do
268
- before do
269
- Split.configuration.experiments = {
270
- :my_experiment => {
271
- :alternatives => ["one", "two"],
272
- :resettable => false,
273
- :metadata => { 'one' => 'Meta1', 'two' => 'Meta2' }
280
+ context 'is defined' do
281
+ before do
282
+ Split.configuration.experiments = {
283
+ :my_experiment => {
284
+ :alternatives => ["one", "two"],
285
+ :resettable => false,
286
+ :metadata => { 'one' => 'Meta1', 'two' => 'Meta2' }
287
+ }
274
288
  }
275
- }
276
- end
289
+ end
277
290
 
278
- it 'should be passed to helper block' do
279
- @params = { 'ab_test' => { 'my_experiment' => 'one' } }
280
- expect(ab_test('my_experiment')).to eq 'one'
281
- expect(ab_test('my_experiment') do |alternative, meta|
282
- meta
283
- end).to eq('Meta1')
291
+ it 'should be passed to helper block' do
292
+ @params = { 'ab_test' => { 'my_experiment' => 'two' } }
293
+ expect(ab_test('my_experiment')).to eq 'two'
294
+ expect(ab_test('my_experiment') do |alternative, meta|
295
+ meta
296
+ end).to eq('Meta2')
297
+ end
298
+
299
+ it 'should pass control metadata helper block if library disabled' do
300
+ Split.configure do |config|
301
+ config.enabled = false
302
+ end
303
+
304
+ expect(ab_test('my_experiment')).to eq 'one'
305
+ expect(ab_test('my_experiment') do |_, meta|
306
+ meta
307
+ end).to eq('Meta1')
308
+ end
284
309
  end
285
310
 
286
- it 'should pass empty hash to helper block if library disabled' do
287
- Split.configure do |config|
288
- config.enabled = false
311
+ context 'is not defined' do
312
+ before do
313
+ Split.configuration.experiments = {
314
+ :my_experiment => {
315
+ :alternatives => ["one", "two"],
316
+ :resettable => false,
317
+ :metadata => nil
318
+ }
319
+ }
320
+ end
321
+
322
+ it 'should be passed to helper block' do
323
+ expect(ab_test('my_experiment') do |alternative, meta|
324
+ meta
325
+ end).to eq({})
289
326
  end
290
327
 
291
- expect(ab_test('my_experiment')).to eq 'one'
292
- expect(ab_test('my_experiment') do |_, meta|
293
- meta
294
- end).to eq({})
328
+ it 'should pass control metadata helper block if library disabled' do
329
+ Split.configure do |config|
330
+ config.enabled = false
331
+ end
332
+
333
+ expect(ab_test('my_experiment') do |_, meta|
334
+ meta
335
+ end).to eq({})
336
+ end
295
337
  end
296
338
  end
297
339
 
@@ -1096,15 +1138,9 @@ describe Split::Helper do
1096
1138
  end
1097
1139
 
1098
1140
  it "should increment the counter for the specified-goal completed alternative" do
1099
- expect(lambda {
1100
- expect(lambda {
1101
- ab_finished({"link_color" => ["purchase"]})
1102
- }).not_to change {
1103
- Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal2)
1104
- }
1105
- }).to change {
1106
- Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal1)
1107
- }.by(1)
1141
+ expect{ ab_finished({"link_color" => ["purchase"]}) }
1142
+ .to change{ Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal2) }.by(0)
1143
+ .and change{ Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal1) }.by(1)
1108
1144
  end
1109
1145
  end
1110
1146
  end
@@ -52,7 +52,7 @@ describe Split::Persistence::CookieAdapter do
52
52
  it "puts multiple experiments in a single cookie" do
53
53
  subject["foo"] = "FOO"
54
54
  subject["bar"] = "BAR"
55
- expect(context.response.headers["Set-Cookie"]).to match(/\Asplit=%7B%22foo%22%3A%22FOO%22%2C%22bar%22%3A%22BAR%22%7D; path=\/; expires=[a-zA-Z]{3}, \d{2} [a-zA-Z]{3} \d{4} \d{2}:\d{2}:\d{2} -0000\Z/)
55
+ expect(context.response.headers["Set-Cookie"]).to match(/\Asplit=%7B%22foo%22%3A%22FOO%22%2C%22bar%22%3A%22BAR%22%7D; path=\/; expires=[a-zA-Z]{3}, \d{2} [a-zA-Z]{3} \d{4} \d{2}:\d{2}:\d{2} [A-Z]{3}\Z/)
56
56
  end
57
57
 
58
58
  it "ensure other added cookies are not overriden" do
@@ -60,6 +60,15 @@ describe Split::Persistence::RedisAdapter do
60
60
  end
61
61
  end
62
62
 
63
+ describe '#find' do
64
+ before { Split::Persistence::RedisAdapter.with_config(:lookup_by => proc{'frag'}, :namespace => 'a_namespace') }
65
+
66
+ it "should create and user from a given key" do
67
+ adapter = Split::Persistence::RedisAdapter.find(2)
68
+ expect(adapter.redis_key).to eq("a_namespace:2")
69
+ end
70
+ end
71
+
63
72
  context 'functional tests' do
64
73
  before { Split::Persistence::RedisAdapter.with_config(:lookup_by => 'lookup') }
65
74
 
@@ -29,75 +29,6 @@ describe Split::RedisInterface do
29
29
  end
30
30
  end
31
31
 
32
- describe '#add_to_list' do
33
- subject(:add_to_list) do
34
- interface.add_to_list(list_name, 'y')
35
- interface.add_to_list(list_name, 'z')
36
- end
37
-
38
- specify do
39
- add_to_list
40
- expect(Split.redis.lindex(list_name, 0)).to eq 'y'
41
- expect(Split.redis.lindex(list_name, 1)).to eq 'z'
42
- expect(Split.redis.llen(list_name)).to eq 2
43
- end
44
- end
45
-
46
- describe '#set_list_index' do
47
- subject(:set_list_index) do
48
- interface.add_to_list(list_name, 'y')
49
- interface.add_to_list(list_name, 'z')
50
- interface.set_list_index(list_name, 0, 'a')
51
- end
52
-
53
- specify do
54
- set_list_index
55
- expect(Split.redis.lindex(list_name, 0)).to eq 'a'
56
- expect(Split.redis.lindex(list_name, 1)).to eq 'z'
57
- expect(Split.redis.llen(list_name)).to eq 2
58
- end
59
- end
60
-
61
- describe '#list_length' do
62
- subject(:list_length) do
63
- interface.add_to_list(list_name, 'y')
64
- interface.add_to_list(list_name, 'z')
65
- interface.list_length(list_name)
66
- end
67
-
68
- specify do
69
- expect(list_length).to eq 2
70
- end
71
- end
72
-
73
- describe '#remove_last_item_from_list' do
74
- subject(:remove_last_item_from_list) do
75
- interface.add_to_list(list_name, 'y')
76
- interface.add_to_list(list_name, 'z')
77
- interface.remove_last_item_from_list(list_name)
78
- end
79
-
80
- specify do
81
- remove_last_item_from_list
82
- expect(Split.redis.lindex(list_name, 0)).to eq 'y'
83
- expect(Split.redis.llen(list_name)).to eq 1
84
- end
85
- end
86
-
87
- describe '#make_list_length' do
88
- subject(:make_list_length) do
89
- interface.add_to_list(list_name, 'y')
90
- interface.add_to_list(list_name, 'z')
91
- interface.make_list_length(list_name, 1)
92
- end
93
-
94
- specify do
95
- make_list_length
96
- expect(Split.redis.lindex(list_name, 0)).to eq 'y'
97
- expect(Split.redis.llen(list_name)).to eq 1
98
- end
99
- end
100
-
101
32
  describe '#add_to_set' do
102
33
  subject(:add_to_set) do
103
34
  interface.add_to_set(set_name, 'something')
@@ -13,17 +13,16 @@ require 'yaml'
13
13
 
14
14
  Dir['./spec/support/*.rb'].each { |f| require f }
15
15
 
16
- require "fakeredis"
17
-
18
- G_fakeredis = Redis.new
19
-
20
16
  module GlobalSharedContext
21
17
  extend RSpec::SharedContext
22
18
  let(:mock_user){ Split::User.new(double(session: {})) }
19
+
23
20
  before(:each) do
24
21
  Split.configuration = Split::Configuration.new
25
- Split.redis = G_fakeredis
26
- Split.redis.flushall
22
+ Split.redis = Redis.new
23
+ Split.redis.select(10)
24
+ Split.redis.flushdb
25
+ Split::Cache.clear
27
26
  @ab_user = mock_user
28
27
  params = nil
29
28
  end
@@ -198,42 +198,68 @@ describe Split::Trial do
198
198
  expect(trial.alternative.name).to_not be_empty
199
199
  Split.configuration.on_trial_choose = nil
200
200
  end
201
+
202
+ it "assigns user to an alternative" do
203
+ trial.choose! context
204
+
205
+ expect(alternatives).to include(user[experiment.name])
206
+ end
207
+
208
+ context "when cohorting is disabled" do
209
+ before(:each) { allow(experiment).to receive(:cohorting_disabled?).and_return(true) }
210
+
211
+ it "picks the control and does not run on_trial callbacks" do
212
+ Split.configuration.on_trial = :on_trial_callback
213
+
214
+ expect(experiment).to_not receive(:next_alternative)
215
+ expect(context).not_to receive(:on_trial_callback)
216
+ expect_alternative(trial, 'basket')
217
+
218
+ Split.configuration.enabled = true
219
+ Split.configuration.on_trial = nil
220
+ end
221
+
222
+ it "user is not assigned an alternative" do
223
+ trial.choose! context
224
+
225
+ expect(user[experiment]).to eq(nil)
226
+ end
227
+ end
201
228
  end
202
229
  end
203
230
 
204
231
  describe "#complete!" do
205
- let(:trial) { Split::Trial.new(:user => user, :experiment => experiment) }
206
232
  context 'when there are no goals' do
233
+ let(:trial) { Split::Trial.new(:user => user, :experiment => experiment) }
207
234
  it 'should complete the trial' do
208
235
  trial.choose!
209
236
  old_completed_count = trial.alternative.completed_count
210
237
  trial.complete!
211
- expect(trial.alternative.completed_count).to be(old_completed_count+1)
238
+ expect(trial.alternative.completed_count).to eq(old_completed_count + 1)
212
239
  end
213
240
  end
214
241
 
215
- context 'when there are many goals' do
216
- let(:goals) { ['first', 'second'] }
242
+ context "when there are many goals" do
243
+ let(:goals) { [ "goal1", "goal2" ] }
217
244
  let(:trial) { Split::Trial.new(:user => user, :experiment => experiment, :goals => goals) }
218
- shared_examples_for "goal completion" do
219
- it 'should not complete the trial' do
220
- trial.choose!
221
- old_completed_count = trial.alternative.completed_count
222
- trial.complete!(goal)
223
- expect(trial.alternative.completed_count).to_not be(old_completed_count+1)
224
- end
225
- end
226
245
 
227
- describe 'Array of Goals' do
228
- let(:goal) { [goals.first] }
229
- it_behaves_like 'goal completion'
246
+ it "increments the completed count corresponding to the goals" do
247
+ trial.choose!
248
+ old_completed_counts = goals.map{ |goal| [goal, trial.alternative.completed_count(goal)] }.to_h
249
+ trial.complete!
250
+ goals.each { | goal | expect(trial.alternative.completed_count(goal)).to eq(old_completed_counts[goal] + 1) }
230
251
  end
252
+ end
231
253
 
232
- describe 'String of Goal' do
233
- let(:goal) { goals.first }
234
- it_behaves_like 'goal completion'
254
+ context "when there is 1 goal of type string" do
255
+ let(:goal) { "goal" }
256
+ let(:trial) { Split::Trial.new(:user => user, :experiment => experiment, :goals => goal) }
257
+ it "increments the completed count corresponding to the goal" do
258
+ trial.choose!
259
+ old_completed_count = trial.alternative.completed_count(goal)
260
+ trial.complete!
261
+ expect(trial.alternative.completed_count(goal)).to eq(old_completed_count + 1)
235
262
  end
236
-
237
263
  end
238
264
  end
239
265
 
@@ -72,6 +72,23 @@ describe Split::User do
72
72
  end
73
73
  end
74
74
 
75
+ context 'allows user to be loaded from adapter' do
76
+ it 'loads user from adapter (RedisAdapter)' do
77
+ user = Split::Persistence::RedisAdapter.new(nil, 112233)
78
+ user['foo'] = 'bar'
79
+
80
+ ab_user = Split::User.find(112233, :redis)
81
+
82
+ expect(ab_user['foo']).to eql('bar')
83
+ end
84
+
85
+ it 'returns nil if adapter does not implement a finder method' do
86
+ ab_user = Split::User.find(112233, :dual_adapter)
87
+ expect(ab_user).to be_nil
88
+ end
89
+
90
+ end
91
+
75
92
  context "instantiated with custom adapter" do
76
93
  let(:custom_adapter) { double(:persistence_adapter) }
77
94
 
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # frozen_string_literal: true
3
+
3
4
  $:.push File.expand_path("../lib", __FILE__)
4
5
  require "split/version"
5
6
 
@@ -22,23 +23,22 @@ Gem::Specification.new do |s|
22
23
  "mailing_list_uri" => "https://groups.google.com/d/forum/split-ruby"
23
24
  }
24
25
 
25
- s.required_ruby_version = '>= 1.9.3'
26
+ s.required_ruby_version = '>= 2.5.0'
26
27
  s.required_rubygems_version = '>= 2.0.0'
27
28
 
28
29
  s.files = `git ls-files`.split("\n")
29
30
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
31
  s.require_paths = ["lib"]
31
32
 
32
- s.add_dependency 'redis', '>= 2.1'
33
+ s.add_dependency 'redis', '>= 4.2'
33
34
  s.add_dependency 'sinatra', '>= 1.2.6'
34
- s.add_dependency 'simple-random', '>= 0.9.3'
35
+ s.add_dependency 'rubystats', '>= 0.3.0'
35
36
 
36
37
  s.add_development_dependency 'bundler', '>= 1.17'
37
38
  s.add_development_dependency 'simplecov', '~> 0.15'
38
- s.add_development_dependency 'rack-test', '~> 0.6'
39
- s.add_development_dependency 'rake', '~> 12'
39
+ s.add_development_dependency 'rack-test', '~> 1.1'
40
+ s.add_development_dependency 'rake', '~> 13'
40
41
  s.add_development_dependency 'rspec', '~> 3.7'
41
42
  s.add_development_dependency 'pry', '~> 0.10'
42
- s.add_development_dependency 'fakeredis', '~> 0.7'
43
- s.add_development_dependency 'rails', '>= 4.2'
43
+ s.add_development_dependency 'rails', '>= 5.0'
44
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: split
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.1
4
+ version: 4.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nesbitt
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-12 00:00:00.000000000 Z
11
+ date: 2020-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.1'
19
+ version: '4.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '2.1'
26
+ version: '4.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sinatra
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.2.6
41
41
  - !ruby/object:Gem::Dependency
42
- name: simple-random
42
+ name: rubystats
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.9.3
47
+ version: 0.3.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.9.3
54
+ version: 0.3.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +86,28 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.6'
89
+ version: '1.1'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.6'
96
+ version: '1.1'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '12'
103
+ version: '13'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '12'
110
+ version: '13'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -136,35 +136,21 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0.10'
139
- - !ruby/object:Gem::Dependency
140
- name: fakeredis
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '0.7'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '0.7'
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: rails
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
143
  - - ">="
158
144
  - !ruby/object:Gem::Version
159
- version: '4.2'
145
+ version: '5.0'
160
146
  type: :development
161
147
  prerelease: false
162
148
  version_requirements: !ruby/object:Gem::Requirement
163
149
  requirements:
164
150
  - - ">="
165
151
  - !ruby/object:Gem::Version
166
- version: '4.2'
167
- description:
152
+ version: '5.0'
153
+ description:
168
154
  email:
169
155
  - andrewnez@gmail.com
170
156
  executables: []
@@ -175,6 +161,7 @@ files:
175
161
  - ".csslintrc"
176
162
  - ".eslintignore"
177
163
  - ".eslintrc"
164
+ - ".github/FUNDING.yml"
178
165
  - ".github/ISSUE_TEMPLATE/bug_report.md"
179
166
  - ".gitignore"
180
167
  - ".rspec"
@@ -189,7 +176,6 @@ files:
189
176
  - LICENSE
190
177
  - README.md
191
178
  - Rakefile
192
- - gemfiles/4.2.gemfile
193
179
  - gemfiles/5.0.gemfile
194
180
  - gemfiles/5.1.gemfile
195
181
  - gemfiles/5.2.gemfile
@@ -199,6 +185,7 @@ files:
199
185
  - lib/split/algorithms/weighted_sample.rb
200
186
  - lib/split/algorithms/whiplash.rb
201
187
  - lib/split/alternative.rb
188
+ - lib/split/cache.rb
202
189
  - lib/split/combined_experiments_helper.rb
203
190
  - lib/split/configuration.rb
204
191
  - lib/split/dashboard.rb
@@ -238,6 +225,7 @@ files:
238
225
  - spec/algorithms/weighted_sample_spec.rb
239
226
  - spec/algorithms/whiplash_spec.rb
240
227
  - spec/alternative_spec.rb
228
+ - spec/cache_spec.rb
241
229
  - spec/combined_experiments_helper_spec.rb
242
230
  - spec/configuration_spec.rb
243
231
  - spec/dashboard/pagination_helpers_spec.rb
@@ -272,7 +260,7 @@ metadata:
272
260
  bug_tracker_uri: https://github.com/splitrb/split/issues
273
261
  wiki_uri: https://github.com/splitrb/split/wiki
274
262
  mailing_list_uri: https://groups.google.com/d/forum/split-ruby
275
- post_install_message:
263
+ post_install_message:
276
264
  rdoc_options: []
277
265
  require_paths:
278
266
  - lib
@@ -280,15 +268,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
280
268
  requirements:
281
269
  - - ">="
282
270
  - !ruby/object:Gem::Version
283
- version: 1.9.3
271
+ version: 2.5.0
284
272
  required_rubygems_version: !ruby/object:Gem::Requirement
285
273
  requirements:
286
274
  - - ">="
287
275
  - !ruby/object:Gem::Version
288
276
  version: 2.0.0
289
277
  requirements: []
290
- rubygems_version: 3.0.3
291
- signing_key:
278
+ rubygems_version: 3.1.4
279
+ signing_key:
292
280
  specification_version: 4
293
281
  summary: Rack based split testing framework
294
282
  test_files:
@@ -296,6 +284,7 @@ test_files:
296
284
  - spec/algorithms/weighted_sample_spec.rb
297
285
  - spec/algorithms/whiplash_spec.rb
298
286
  - spec/alternative_spec.rb
287
+ - spec/cache_spec.rb
299
288
  - spec/combined_experiments_helper_spec.rb
300
289
  - spec/configuration_spec.rb
301
290
  - spec/dashboard/pagination_helpers_spec.rb