split 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ ## 0.3.2 (February 12, 2012)
2
+
3
+ Features:
4
+
5
+ - Handle redis errors gracefully (@layflags, #32)
6
+
1
7
  ## 0.3.1 (November 19, 2011)
2
8
 
3
9
  Features:
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Andrew Nesbitt
1
+ Copyright (c) 2012 Andrew Nesbitt
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -81,14 +81,14 @@ Example: Controller
81
81
 
82
82
  def register_new_user
83
83
  # See what level of free points maximizes users' decision to buy replacement points.
84
- @starter_points = ab_test("new_user_free_points", 100, 200, 300)
84
+ @starter_points = ab_test("new_user_free_points", '100', '200', '300')
85
85
  end
86
86
 
87
87
  Example: Conversion tracking (in a controller!)
88
88
 
89
89
  def buy_new_points
90
90
  # some business logic
91
- finished("buy_new_points")
91
+ finished("new_user_free_points")
92
92
  end
93
93
 
94
94
  Example: Conversion tracking (in a view)
@@ -251,4 +251,4 @@ Tests can be ran with `rake spec`
251
251
 
252
252
  ## Copyright
253
253
 
254
- Copyright (c) 2011 Andrew Nesbitt. See [LICENSE](https://github.com/andrew/split/blob/master/LICENSE) for details.
254
+ Copyright (c) 2012 Andrew Nesbitt. See [LICENSE](https://github.com/andrew/split/blob/master/LICENSE) for details.
@@ -2,10 +2,14 @@ module Split
2
2
  class Configuration
3
3
  attr_accessor :robot_regex
4
4
  attr_accessor :ignore_ip_addresses
5
+ attr_accessor :db_failover
6
+ attr_accessor :db_failover_on_db_error
5
7
 
6
8
  def initialize
7
9
  @robot_regex = /\b(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg)\b/i
8
10
  @ignore_ip_addresses = []
11
+ @db_failover = false
12
+ @db_failover_on_db_error = proc{|error|} # e.g. use Rails logger here
9
13
  end
10
14
  end
11
15
  end
@@ -32,6 +32,12 @@ module Split
32
32
  else
33
33
  ret
34
34
  end
35
+ rescue Errno::ECONNREFUSED => e
36
+ raise unless Split.configuration.db_failover
37
+ Split.configuration.db_failover_on_db_error.call(e)
38
+ ret = Hash === (a0 = alternatives.first) ? a0.keys.first : a0
39
+ yield(ret) if block_given?
40
+ ret
35
41
  end
36
42
 
37
43
  def finished(experiment_name, options = {:reset => true})
@@ -42,6 +48,9 @@ module Split
42
48
  alternative.increment_completion
43
49
  session[:split].delete(experiment_name) if options[:reset]
44
50
  end
51
+ rescue Errno::ECONNREFUSED => e
52
+ raise unless Split.configuration.db_failover
53
+ Split.configuration.db_failover_on_db_error.call(e)
45
54
  end
46
55
 
47
56
  def override(experiment_name, alternatives)
@@ -1,3 +1,3 @@
1
1
  module Split
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -6,5 +6,7 @@ describe Split::Configuration do
6
6
 
7
7
  config.ignore_ip_addresses.should eql([])
8
8
  config.robot_regex.should eql(/\b(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg)\b/i)
9
+ config.db_failover.should be_false
10
+ config.db_failover_on_db_error.should be_a Proc
9
11
  end
10
- end
12
+ end
@@ -68,6 +68,7 @@ describe Split::Helper do
68
68
  experiment = Split::Experiment.find('link_color')
69
69
  experiment.alternative_names.should eql(['blue', 'red'])
70
70
  end
71
+
71
72
  end
72
73
 
73
74
  describe 'finished' do
@@ -271,4 +272,87 @@ describe Split::Helper do
271
272
  alternative.completed_count.should eql(0)
272
273
  end
273
274
  end
274
- end
275
+
276
+ context 'when redis is not available' do
277
+
278
+ before(:each) do
279
+ Split.stub(:redis).and_raise(Errno::ECONNREFUSED)
280
+ end
281
+
282
+ context 'and db_failover config option is turned off' do
283
+
284
+ describe 'ab_test' do
285
+ it 'should raise an exception' do
286
+ lambda {
287
+ ab_test('link_color', 'blue', 'red')
288
+ }.should raise_error(Errno::ECONNREFUSED)
289
+ end
290
+ end
291
+
292
+ describe 'finished' do
293
+ it 'should raise an exception' do
294
+ lambda {
295
+ finished('link_color')
296
+ }.should raise_error(Errno::ECONNREFUSED)
297
+ end
298
+ end
299
+
300
+ end
301
+
302
+ context 'and db_failover config option is turned on' do
303
+
304
+ before(:each) do
305
+ Split.configure do |config|
306
+ config.db_failover = true
307
+ end
308
+ end
309
+
310
+ describe 'ab_test' do
311
+ it 'should not raise an exception' do
312
+ lambda {
313
+ ab_test('link_color', 'blue', 'red')
314
+ }.should_not raise_error(Errno::ECONNREFUSED)
315
+ end
316
+ it 'should call db_failover_on_db_error proc with error as parameter' do
317
+ Split.configure do |config|
318
+ config.db_failover_on_db_error = proc do |error|
319
+ error.should be_a(Errno::ECONNREFUSED)
320
+ end
321
+ end
322
+ Split.configuration.db_failover_on_db_error.should_receive(:call)
323
+ ab_test('link_color', 'blue', 'red')
324
+ end
325
+ it 'should always use first alternative' do
326
+ 10.times do
327
+ ab_test('link_color', 'blue', 'red').should eq('blue')
328
+ ab_test('link_color', 'blue' => 0.01, 'red' => 0.2).should eq('blue')
329
+ ab_test('link_color', {'blue' => 0.8}, {'red' => 20}).should eq('blue')
330
+ ab_test('link_color', 'blue', 'red') do |link_color|
331
+ link_color.should eq('blue')
332
+ end
333
+ end
334
+ end
335
+ end
336
+
337
+ describe 'finished' do
338
+ it 'should not raise an exception' do
339
+ lambda {
340
+ finished('link_color')
341
+ }.should_not raise_error(Errno::ECONNREFUSED)
342
+ end
343
+ it 'should call db_failover_on_db_error proc with error as parameter' do
344
+ Split.configure do |config|
345
+ config.db_failover_on_db_error = proc do |error|
346
+ error.should be_a(Errno::ECONNREFUSED)
347
+ end
348
+ end
349
+ Split.configuration.db_failover_on_db_error.should_receive(:call)
350
+ finished('link_color')
351
+ end
352
+ end
353
+
354
+ end
355
+
356
+ end
357
+
358
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: split
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-19 00:00:00.000000000Z
12
+ date: 2012-02-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &70308912822720 !ruby/object:Gem::Requirement
16
+ requirement: &70251262594940 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70308912822720
24
+ version_requirements: *70251262594940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis-namespace
27
- requirement: &70308912821980 !ruby/object:Gem::Requirement
27
+ requirement: &70251262594280 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.3
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70308912821980
35
+ version_requirements: *70251262594280
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sinatra
38
- requirement: &70308912821300 !ruby/object:Gem::Requirement
38
+ requirement: &70251262592740 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.2.6
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70308912821300
46
+ version_requirements: *70251262592740
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rake
49
- requirement: &70308912820460 !ruby/object:Gem::Requirement
49
+ requirement: &70251262591720 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70308912820460
57
+ version_requirements: *70251262591720
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: bundler
60
- requirement: &70308912819780 !ruby/object:Gem::Requirement
60
+ requirement: &70251262589960 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '1.0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70308912819780
68
+ version_requirements: *70251262589960
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70308912819060 !ruby/object:Gem::Requirement
71
+ requirement: &70251262588940 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '2.6'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70308912819060
79
+ version_requirements: *70251262588940
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rack-test
82
- requirement: &70308912818400 !ruby/object:Gem::Requirement
82
+ requirement: &70251262585780 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0.6'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70308912818400
90
+ version_requirements: *70251262585780
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: guard-rspec
93
- requirement: &70308912817760 !ruby/object:Gem::Requirement
93
+ requirement: &70251262579760 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0.4'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70308912817760
101
+ version_requirements: *70251262579760
102
102
  description:
103
103
  email:
104
104
  - andrewnez@gmail.com
@@ -145,18 +145,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
145
  - - ! '>='
146
146
  - !ruby/object:Gem::Version
147
147
  version: '0'
148
- segments:
149
- - 0
150
- hash: -3943651241702022185
151
148
  required_rubygems_version: !ruby/object:Gem::Requirement
152
149
  none: false
153
150
  requirements:
154
151
  - - ! '>='
155
152
  - !ruby/object:Gem::Version
156
153
  version: '0'
157
- segments:
158
- - 0
159
- hash: -3943651241702022185
160
154
  requirements: []
161
155
  rubyforge_project: split
162
156
  rubygems_version: 1.8.6