trailguide 0.1.12 → 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/trail_guide/admin/experiments_controller.rb +5 -0
- data/app/views/trail_guide/admin/experiments/_experiment.html.erb +4 -2
- data/config/routes.rb +1 -0
- data/lib/trail_guide/experiment.rb +31 -6
- data/lib/trail_guide/experiment_config.rb +5 -0
- data/lib/trail_guide/participant.rb +4 -2
- data/lib/trail_guide/version.rb +1 -1
- data/lib/trailguide.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c626f06613b7702e01f9c19ef77f6f77e022f0c1280cc13205e46a95bc3ff548
|
4
|
+
data.tar.gz: a91f183473695792a9c067d3ca8e59d91177b0bf97bc1ae29d34c976ba177760
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0952f9bdb7840f6e201f78a0eb46bfcfe296bcfb115db735062923a8ae9e670c194e7c244225471a1484eaa4649a80f0612061fa4c1c81e7fa0c4824e89ddb3
|
7
|
+
data.tar.gz: 5432d3d30169caa958a344f99d732f389cd1ed23c052a41a0f86a6ef1b39ad2fac7e337dc81d586875d190d3ef9f2236d3abf81268f8ee3714458582409a86b7
|
@@ -23,6 +23,11 @@ module TrailGuide
|
|
23
23
|
redirect_to :back rescue redirect_to trail_guide_admin.experiments_path
|
24
24
|
end
|
25
25
|
|
26
|
+
def resume
|
27
|
+
experiment.resume!
|
28
|
+
redirect_to :back rescue redirect_to trail_guide_admin.experiments_path
|
29
|
+
end
|
30
|
+
|
26
31
|
def restart
|
27
32
|
experiment.reset! && experiment.start!
|
28
33
|
redirect_to :back rescue redirect_to trail_guide_admin.experiments_path
|
@@ -10,13 +10,15 @@
|
|
10
10
|
</h3>
|
11
11
|
</div>
|
12
12
|
<div class="col-sm-12 col-md-6 col-lg-4 text-right">
|
13
|
-
<% if experiment.
|
13
|
+
<% if experiment.running? %>
|
14
14
|
<%= link_to "stop", trail_guide_admin.stop_experiment_path(experiment.experiment_name), class: 'btn btn-sm btn-warning', method: :put %>
|
15
15
|
<%= link_to "restart", trail_guide_admin.restart_experiment_path(experiment.experiment_name), class: 'btn btn-sm btn-danger',method: :put %>
|
16
|
+
<% elsif experiment.started? %>
|
17
|
+
<%= link_to "resume", trail_guide_admin.resume_experiment_path(experiment.experiment_name), class: 'btn btn-sm btn-primary',method: :put %>
|
16
18
|
<% else %>
|
17
19
|
<%= link_to "start", trail_guide_admin.start_experiment_path(experiment.experiment_name), class: 'btn btn-sm btn-success',method: :put %>
|
18
20
|
<% end %>
|
19
|
-
<%= link_to "reset", trail_guide_admin.reset_experiment_path(experiment.experiment_name), class: 'btn btn-sm btn-danger',method: :put %>
|
21
|
+
<%= link_to "reset", trail_guide_admin.reset_experiment_path(experiment.experiment_name), class: 'btn btn-sm btn-outline-danger',method: :put %>
|
20
22
|
</div>
|
21
23
|
</div>
|
22
24
|
|
data/config/routes.rb
CHANGED
@@ -19,6 +19,7 @@ if defined?(TrailGuide::Admin::Engine)
|
|
19
19
|
match :start, via: [:put, :post, :get]
|
20
20
|
match :stop, via: [:put, :post, :get]
|
21
21
|
match :reset, via: [:put, :post, :get]
|
22
|
+
match :resume, via: [:put, :post, :get]
|
22
23
|
match :restart, via: [:put, :post, :get]
|
23
24
|
match :winner, via: [:put, :post, :get], path: 'winner/:variant'
|
24
25
|
end
|
@@ -56,26 +56,50 @@ module TrailGuide
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def stop!
|
59
|
-
return false unless
|
60
|
-
stopped = TrailGuide.redis.
|
59
|
+
return false unless running?
|
60
|
+
stopped = TrailGuide.redis.hset(storage_key, 'stopped_at', Time.now.to_i)
|
61
61
|
run_callbacks(:on_stop)
|
62
62
|
stopped
|
63
63
|
end
|
64
64
|
|
65
|
+
def resume!
|
66
|
+
return false unless started? && stopped?
|
67
|
+
restarted = TrailGuide.redis.hdel(storage_key, 'stopped_at')
|
68
|
+
run_callbacks(:on_resume)
|
69
|
+
restarted
|
70
|
+
end
|
71
|
+
|
65
72
|
def started_at
|
66
73
|
started = TrailGuide.redis.hget(storage_key, 'started_at')
|
67
74
|
return Time.at(started.to_i) if started
|
68
75
|
end
|
69
76
|
|
77
|
+
def stopped_at
|
78
|
+
stopped = TrailGuide.redis.hget(storage_key, 'stopped_at')
|
79
|
+
return Time.at(stopped.to_i) if stopped
|
80
|
+
end
|
81
|
+
|
70
82
|
def started?
|
71
83
|
!!started_at
|
72
84
|
end
|
73
85
|
|
86
|
+
def stopped?
|
87
|
+
!!stopped_at
|
88
|
+
end
|
89
|
+
|
90
|
+
def running?
|
91
|
+
started? && !stopped?
|
92
|
+
end
|
93
|
+
|
74
94
|
def declare_winner!(variant)
|
75
95
|
variant = variant.name if variant.is_a?(Variant)
|
76
96
|
TrailGuide.redis.hset(storage_key, 'winner', variant.to_s.underscore)
|
77
97
|
end
|
78
98
|
|
99
|
+
def clear_winner!
|
100
|
+
TrailGuide.redis.hdel(storage_key, 'winner')
|
101
|
+
end
|
102
|
+
|
79
103
|
def winner
|
80
104
|
winner = TrailGuide.redis.hget(storage_key, 'winner')
|
81
105
|
return variants.find { |var| var == winner } if winner
|
@@ -133,9 +157,9 @@ module TrailGuide
|
|
133
157
|
|
134
158
|
attr_reader :participant
|
135
159
|
delegate :configuration, :experiment_name, :variants, :control, :funnels,
|
136
|
-
:storage_key, :started?, :started_at, :start!, :resettable?,
|
137
|
-
:winner, :allow_multiple_conversions?, :allow_multiple_goals?,
|
138
|
-
to: :class
|
160
|
+
:storage_key, :running?, :started?, :started_at, :start!, :resettable?,
|
161
|
+
:winner?, :winner, :allow_multiple_conversions?, :allow_multiple_goals?,
|
162
|
+
:callbacks, to: :class
|
139
163
|
|
140
164
|
def initialize(participant)
|
141
165
|
@participant = participant
|
@@ -158,12 +182,13 @@ module TrailGuide
|
|
158
182
|
return control if TrailGuide.configuration.disabled
|
159
183
|
if override.present?
|
160
184
|
variant = variants.find { |var| var == override }
|
161
|
-
return variant unless configuration.track_override &&
|
185
|
+
return variant unless configuration.track_override && running?
|
162
186
|
else
|
163
187
|
return winner if winner?
|
164
188
|
return control if excluded
|
165
189
|
return control if !started? && configuration.start_manually
|
166
190
|
start! unless started?
|
191
|
+
return control unless running?
|
167
192
|
return variants.find { |var| var == participant[storage_key] } if participating?
|
168
193
|
return control unless TrailGuide.configuration.allow_multiple_experiments == true || !participant.participating_in_active_experiments?(TrailGuide.configuration.allow_multiple_experiments == false)
|
169
194
|
|
@@ -23,6 +23,7 @@ module TrailGuide
|
|
23
23
|
on_convert: [TrailGuide.configuration.on_experiment_convert].flatten.compact,
|
24
24
|
on_start: [TrailGuide.configuration.on_experiment_start].flatten.compact,
|
25
25
|
on_stop: [TrailGuide.configuration.on_experiment_stop].flatten.compact,
|
26
|
+
on_resume: [TrailGuide.configuration.on_experiment_resume].flatten.compact,
|
26
27
|
on_reset: [TrailGuide.configuration.on_experiment_reset].flatten.compact,
|
27
28
|
on_delete: [TrailGuide.configuration.on_experiment_delete].flatten.compact,
|
28
29
|
}
|
@@ -121,6 +122,10 @@ module TrailGuide
|
|
121
122
|
callbacks[:on_stop] << (meth || block)
|
122
123
|
end
|
123
124
|
|
125
|
+
def on_resume(meth=nil, &block)
|
126
|
+
callbacks[:on_resume] << (meth || block)
|
127
|
+
end
|
128
|
+
|
124
129
|
def on_reset(meth=nil, &block)
|
125
130
|
callbacks[:on_reset] << (meth || block)
|
126
131
|
end
|
@@ -30,6 +30,7 @@ module TrailGuide
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def participating?(experiment, include_control=true)
|
33
|
+
return false unless experiment.started?
|
33
34
|
return false unless adapter.key?(experiment.storage_key)
|
34
35
|
varname = adapter[experiment.storage_key]
|
35
36
|
variant = experiment.variants.find { |var| var == varname }
|
@@ -41,6 +42,7 @@ module TrailGuide
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def converted?(experiment, checkpoint=nil)
|
45
|
+
return false unless experiment.started?
|
44
46
|
if experiment.funnels.empty?
|
45
47
|
raise InvalidGoalError, "You provided the checkpoint `#{checkpoint}` but the experiment `#{experiment.experiment_name}` does not have any goals defined." unless checkpoint.nil?
|
46
48
|
storage_key = "#{experiment.storage_key}:converted"
|
@@ -92,7 +94,7 @@ module TrailGuide
|
|
92
94
|
return false if adapter.keys.empty?
|
93
95
|
adapter.keys.map { |key| key.to_s.split(":").first.to_sym }.uniq.map do |key|
|
94
96
|
experiment = TrailGuide.catalog.find(key)
|
95
|
-
next unless experiment && experiment.
|
97
|
+
next unless experiment && experiment.running? && participating?(experiment, include_control)
|
96
98
|
[ experiment.experiment_name, adapter[experiment.storage_key] ]
|
97
99
|
end.compact.to_h
|
98
100
|
end
|
@@ -103,7 +105,7 @@ module TrailGuide
|
|
103
105
|
adapter.keys.any? do |key|
|
104
106
|
experiment_name = key.to_s.split(":").first.to_sym
|
105
107
|
experiment = TrailGuide.catalog.find(experiment_name)
|
106
|
-
experiment && experiment.
|
108
|
+
experiment && experiment.running? && participating?(experiment, include_control)
|
107
109
|
end
|
108
110
|
end
|
109
111
|
end
|
data/lib/trail_guide/version.rb
CHANGED
data/lib/trailguide.rb
CHANGED
@@ -33,6 +33,7 @@ module TrailGuide
|
|
33
33
|
|
34
34
|
config.on_experiment_start = nil # -> (experiment) { ... }
|
35
35
|
config.on_experiment_stop = nil # -> (experiment) { ... }
|
36
|
+
config.on_experiment_resume = nil # -> (experiment) { ... }
|
36
37
|
config.on_experiment_reset = nil # -> (experiment) { ... }
|
37
38
|
config.on_experiment_delete = nil # -> (experiment) { ... }
|
38
39
|
|