trailguide 0.1.13 → 0.1.14
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.
- checksums.yaml +4 -4
- data/app/controllers/trail_guide/admin/application_controller.rb +1 -1
- data/app/controllers/trail_guide/admin/experiments_controller.rb +29 -6
- data/app/views/trail_guide/admin/experiments/_combined_experiment.html.erb +129 -0
- data/app/views/trail_guide/admin/experiments/_experiment.html.erb +35 -10
- data/app/views/trail_guide/admin/experiments/index.html.erb +6 -2
- data/config/routes.rb +5 -0
- data/lib/trail_guide/catalog.rb +42 -2
- data/lib/trail_guide/combined_experiment.rb +48 -0
- data/lib/trail_guide/engine.rb +1 -0
- data/lib/trail_guide/experiment.rb +4 -237
- data/lib/trail_guide/experiments/base.rb +268 -0
- data/lib/trail_guide/experiments/combined_config.rb +12 -0
- data/lib/trail_guide/experiments/config.rb +158 -0
- data/lib/trail_guide/helper.rb +1 -1
- data/lib/trail_guide/participant.rb +19 -4
- data/lib/trail_guide/version.rb +1 -1
- data/lib/trailguide.rb +5 -0
- metadata +7 -3
- data/lib/trail_guide/experiment_config.rb +0 -137
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e92b5781f0ec93e65f9538268fd8fa00b5be79008ed83337de2b7091020de719
|
4
|
+
data.tar.gz: 547d8afc88e203a7ce6d0995d0efaa0e582b643c80cc0ffdfc7b2743c31aa18b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96d7e94e72fb228b63cac5331d74b8ec5440ad234e4350b47191343b797c83ad50d35a0c9d87131dfc8157fa99355df7e36cff159ce05ab88e70ae5b6315e02d
|
7
|
+
data.tar.gz: 1323352dda2d506d4153c9b70bffd90250077b4b9728fa732f878ca181670921758a4508754e5d38484ced8b8cd684eaa06d0489631b02a15f8261a3b7438efa
|
@@ -10,32 +10,50 @@ module TrailGuide
|
|
10
10
|
|
11
11
|
def start
|
12
12
|
experiment.start!
|
13
|
-
redirect_to :
|
13
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
14
14
|
end
|
15
15
|
|
16
16
|
def stop
|
17
17
|
experiment.stop!
|
18
|
-
redirect_to :
|
18
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
19
19
|
end
|
20
20
|
|
21
21
|
def reset
|
22
22
|
experiment.reset!
|
23
|
-
redirect_to :
|
23
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
24
24
|
end
|
25
25
|
|
26
26
|
def resume
|
27
27
|
experiment.resume!
|
28
|
-
redirect_to :
|
28
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
29
29
|
end
|
30
30
|
|
31
31
|
def restart
|
32
32
|
experiment.reset! && experiment.start!
|
33
|
-
redirect_to :
|
33
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def join
|
37
|
+
participant.exit!(experiment)
|
38
|
+
variant = experiment.variants.find { |var| var == params[:variant] }
|
39
|
+
variant.increment_participation!
|
40
|
+
participant.participating!(variant)
|
41
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def leave
|
45
|
+
participant.exit!(experiment)
|
46
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
34
47
|
end
|
35
48
|
|
36
49
|
def winner
|
37
50
|
experiment.declare_winner!(params[:variant])
|
38
|
-
redirect_to :
|
51
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def clear
|
55
|
+
experiment.clear_winner!
|
56
|
+
redirect_to trail_guide_admin.experiments_path(anchor: experiment.experiment_name)
|
39
57
|
end
|
40
58
|
|
41
59
|
private
|
@@ -43,6 +61,11 @@ module TrailGuide
|
|
43
61
|
def experiment
|
44
62
|
@experiment ||= TrailGuide.catalog.find(params[:id])
|
45
63
|
end
|
64
|
+
|
65
|
+
def participant
|
66
|
+
@participant ||= TrailGuide::Participant.new(self)
|
67
|
+
end
|
68
|
+
helper_method :participant
|
46
69
|
end
|
47
70
|
end
|
48
71
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
<div class="row justify-content-center">
|
2
|
+
<div class="col-sm-12 col-md-10 col-lg-8">
|
3
|
+
<div class="row">
|
4
|
+
<div class="col-sm-12 col-md-6 col-lg-8">
|
5
|
+
<h3 style="margin: 0; padding: 0;" id="<%= combined_experiment.experiment_name %>">
|
6
|
+
<%= link_to combined_experiment.experiment_name.to_s.humanize.titleize, trail_guide_admin.experiments_path(anchor: combined_experiment.experiment_name), class: "text-dark" %>
|
7
|
+
</h3>
|
8
|
+
</div>
|
9
|
+
<div class="col-sm-12 col-md-6 col-lg-4 text-right">
|
10
|
+
<% if combined_experiment.running? %>
|
11
|
+
<%= link_to "stop", trail_guide_admin.stop_experiment_path(combined_experiment.experiment_name), class: 'btn btn-sm btn-warning', method: :put %>
|
12
|
+
<%= link_to "restart", trail_guide_admin.restart_experiment_path(combined_experiment.experiment_name), class: 'btn btn-sm btn-danger',method: :put %>
|
13
|
+
<% elsif combined_experiment.started? %>
|
14
|
+
<%= link_to "resume", trail_guide_admin.resume_experiment_path(combined_experiment.experiment_name), class: 'btn btn-sm btn-primary',method: :put %>
|
15
|
+
<% else %>
|
16
|
+
<%= link_to "start", trail_guide_admin.start_experiment_path(combined_experiment.experiment_name), class: 'btn btn-sm btn-success',method: :put %>
|
17
|
+
<% end %>
|
18
|
+
<%= link_to "reset", trail_guide_admin.reset_experiment_path(combined_experiment.experiment_name), class: 'btn btn-sm btn-outline-danger',method: :put %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div class="row">
|
23
|
+
<div class="col-sm-12 text-right">
|
24
|
+
<% if combined_experiment.started? %>
|
25
|
+
<small class="text-muted"><%= combined_experiment.started_at.strftime('%b %e %Y @ %l:%M %p') %></small>
|
26
|
+
<span class="text-muted">—</span>
|
27
|
+
<% if combined_experiment.stopped? %>
|
28
|
+
<small class="text-muted"><%= combined_experiment.stopped_at.strftime('%b %e %Y @ %l:%M %p') %></small>
|
29
|
+
<% else %>
|
30
|
+
<small class="text-muted">running</small>
|
31
|
+
<% end %>
|
32
|
+
<% else %>
|
33
|
+
<small class="text-muted">not running</small>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<table class="table table-hover">
|
39
|
+
<% combined_experiments = combined_experiment.combined.map { |e| TrailGuide.catalog.find(e) } %>
|
40
|
+
<% combined_experiments.each do |experiment| %>
|
41
|
+
<thead class="thead-light">
|
42
|
+
<tr>
|
43
|
+
<th scope="col">
|
44
|
+
<h4 style="margin: 0; padding: 0" id="<%= experiment.experiment_name %>">
|
45
|
+
<%= link_to experiment.experiment_name.to_s.humanize.titleize, trail_guide_admin.experiments_path(anchor: experiment.experiment_name), class: "text-dark" %>
|
46
|
+
</h4>
|
47
|
+
</th>
|
48
|
+
|
49
|
+
<th scope="col">Participants</th>
|
50
|
+
|
51
|
+
<% if experiment.goals.empty? %>
|
52
|
+
<th scope="col">Converted</th>
|
53
|
+
<% else %>
|
54
|
+
<% experiment.goals.each do |goal| %>
|
55
|
+
<th scope="col"><%= goal.to_s.humanize.titleize %></th>
|
56
|
+
<% end %>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<th> </th>
|
60
|
+
</tr>
|
61
|
+
</thead>
|
62
|
+
|
63
|
+
<tbody>
|
64
|
+
<% experiment.variants.each do |variant| %>
|
65
|
+
<tr class="<%= "table-secondary" if variant.control? %>">
|
66
|
+
<th scope="row">
|
67
|
+
<%= variant.name.to_s.humanize.titleize %>
|
68
|
+
<% if experiment.running? && !experiment.winner? && participant.variant(experiment) == variant %>
|
69
|
+
<span class="badge badge-secondary">joined</span>
|
70
|
+
<% end %>
|
71
|
+
<% if experiment.winner? && variant == experiment.winner %>
|
72
|
+
<span class="badge badge-primary">winner</span>
|
73
|
+
<% end %>
|
74
|
+
<% if variant.control? %>
|
75
|
+
<small class="text-muted">control</small>
|
76
|
+
<% end %>
|
77
|
+
</th>
|
78
|
+
|
79
|
+
<td><%= variant.participants %></td>
|
80
|
+
|
81
|
+
<% if experiment.goals.empty? %>
|
82
|
+
<td><%= variant.converted %></td>
|
83
|
+
<% else %>
|
84
|
+
<% experiment.goals.each do |goal| %>
|
85
|
+
<td><%= variant.converted(goal) %></td>
|
86
|
+
<% end %>
|
87
|
+
<% end %>
|
88
|
+
|
89
|
+
<td class="text-right">
|
90
|
+
<% if experiment.running? && !experiment.winner? %>
|
91
|
+
<% if participant.variant(experiment) == variant %>
|
92
|
+
<%= link_to "leave group", trail_guide_admin.leave_experiment_path(experiment.experiment_name), class: "btn btn-sm btn-outline-secondary", method: :put %>
|
93
|
+
<% else %>
|
94
|
+
<%= link_to "enter group", trail_guide_admin.join_experiment_path(experiment.experiment_name, variant.name), class: "btn btn-sm btn-secondary", method: :put %>
|
95
|
+
<% end %>
|
96
|
+
<% end %>
|
97
|
+
|
98
|
+
<% if !experiment.winner? || variant != experiment.winner %>
|
99
|
+
<%= link_to "select winner", trail_guide_admin.winner_experiment_path(experiment.experiment_name, variant.name), class: "btn btn-sm btn-#{experiment.winner? ? "outline-" : ""}primary", method: :put %>
|
100
|
+
<% elsif experiment.winner? && variant == experiment.winner %>
|
101
|
+
<%= link_to "remove winner", trail_guide_admin.clear_experiment_path(experiment.experiment_name), class: "btn btn-sm btn-warning", method: :put %>
|
102
|
+
<% end %>
|
103
|
+
</td>
|
104
|
+
</tr>
|
105
|
+
<% end %>
|
106
|
+
</tbody>
|
107
|
+
<% end %>
|
108
|
+
|
109
|
+
<tfoot class="thead-light">
|
110
|
+
<tr>
|
111
|
+
<th scope="row">Totals</th>
|
112
|
+
<th><%= combined_experiment.variants.sum(&:participants) %></th>
|
113
|
+
<% if combined_experiment.goals.empty? %>
|
114
|
+
<th><%= combined_experiments.sum { |e| e.variants.sum(&:converted) } %></th>
|
115
|
+
<% else %>
|
116
|
+
<% combined_experiment.goals.each do |goal| %>
|
117
|
+
<th><%= combined_experiments.sum { |e| e.variants.sum { |v| v.converted(goal) } } %></th>
|
118
|
+
<% end %>
|
119
|
+
<% end %>
|
120
|
+
<th> </th>
|
121
|
+
</tr>
|
122
|
+
</tfoot>
|
123
|
+
</table>
|
124
|
+
</div>
|
125
|
+
</div>
|
126
|
+
|
127
|
+
<br />
|
128
|
+
<br />
|
129
|
+
<br />
|
@@ -2,11 +2,8 @@
|
|
2
2
|
<div class="col-sm-12 col-md-10 col-lg-8">
|
3
3
|
<div class="row">
|
4
4
|
<div class="col-sm-12 col-md-6 col-lg-8">
|
5
|
-
<h3>
|
6
|
-
<%= experiment.experiment_name.to_s.humanize.titleize %>
|
7
|
-
<% if experiment.started? %>
|
8
|
-
<small class="text-muted"><%= experiment.started_at.strftime('%b %e %Y @ %l:%M %p') %></small>
|
9
|
-
<% end %>
|
5
|
+
<h3 style="margin: 0; padding: 0;" id="<%= experiment.experiment_name %>">
|
6
|
+
<%= link_to experiment.experiment_name.to_s.humanize.titleize, trail_guide_admin.experiments_path(anchor: experiment.experiment_name), class: "text-dark" %>
|
10
7
|
</h3>
|
11
8
|
</div>
|
12
9
|
<div class="col-sm-12 col-md-6 col-lg-4 text-right">
|
@@ -22,6 +19,22 @@
|
|
22
19
|
</div>
|
23
20
|
</div>
|
24
21
|
|
22
|
+
<div class="row">
|
23
|
+
<div class="col-sm-12 text-right">
|
24
|
+
<% if experiment.started? %>
|
25
|
+
<small class="text-muted"><%= experiment.started_at.strftime('%b %e %Y @ %l:%M %p') %></small>
|
26
|
+
<span class="text-muted">—</span>
|
27
|
+
<% if experiment.stopped? %>
|
28
|
+
<small class="text-muted"><%= experiment.stopped_at.strftime('%b %e %Y @ %l:%M %p') %></small>
|
29
|
+
<% else %>
|
30
|
+
<small class="text-muted">running</small>
|
31
|
+
<% end %>
|
32
|
+
<% else %>
|
33
|
+
<small class="text-muted">not running</small>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
|
25
38
|
<table class="table table-hover">
|
26
39
|
<thead class="thead-light">
|
27
40
|
<tr>
|
@@ -46,6 +59,12 @@
|
|
46
59
|
<tr class="<%= "table-secondary" if variant.control? %>">
|
47
60
|
<th scope="row">
|
48
61
|
<%= variant.name.to_s.humanize.titleize %>
|
62
|
+
<% if experiment.running? && !experiment.winner? && participant.variant(experiment) == variant %>
|
63
|
+
<span class="badge badge-secondary">joined</span>
|
64
|
+
<% end %>
|
65
|
+
<% if experiment.winner? && variant == experiment.winner %>
|
66
|
+
<span class="badge badge-primary">winner</span>
|
67
|
+
<% end %>
|
49
68
|
<% if variant.control? %>
|
50
69
|
<small class="text-muted">control</small>
|
51
70
|
<% end %>
|
@@ -62,12 +81,18 @@
|
|
62
81
|
<% end %>
|
63
82
|
|
64
83
|
<td class="text-right">
|
65
|
-
<% if experiment.winner? %>
|
66
|
-
<% if variant ==
|
67
|
-
|
84
|
+
<% if experiment.running? && !experiment.winner? %>
|
85
|
+
<% if participant.variant(experiment) == variant %>
|
86
|
+
<%= link_to "leave group", trail_guide_admin.leave_experiment_path(experiment.experiment_name), class: "btn btn-sm btn-outline-secondary", method: :put %>
|
87
|
+
<% else %>
|
88
|
+
<%= link_to "enter group", trail_guide_admin.join_experiment_path(experiment.experiment_name, variant.name), class: "btn btn-sm btn-secondary", method: :put %>
|
68
89
|
<% end %>
|
69
|
-
<%
|
70
|
-
|
90
|
+
<% end %>
|
91
|
+
|
92
|
+
<% if !experiment.winner? || variant != experiment.winner %>
|
93
|
+
<%= link_to "select winner", trail_guide_admin.winner_experiment_path(experiment.experiment_name, variant.name), class: "btn btn-sm btn-#{experiment.winner? ? "outline-" : ""}primary", method: :put %>
|
94
|
+
<% elsif experiment.winner? && variant == experiment.winner %>
|
95
|
+
<%= link_to "remove winner", trail_guide_admin.clear_experiment_path(experiment.experiment_name), class: "btn btn-sm btn-warning", method: :put %>
|
71
96
|
<% end %>
|
72
97
|
</td>
|
73
98
|
</tr>
|
@@ -1,13 +1,17 @@
|
|
1
1
|
<div class="container-fluid">
|
2
2
|
<div class="row justify-content-center">
|
3
3
|
<div class="col-sm-12 col-md-10 col-lg-8">
|
4
|
-
<h1
|
4
|
+
<h1><%= link_to "Experiments", trail_guide_admin.experiments_path, class: "text-dark" %></h1>
|
5
5
|
</div>
|
6
6
|
</div>
|
7
7
|
|
8
8
|
<hr />
|
9
9
|
|
10
10
|
<% TrailGuide.catalog.each do |experiment| %>
|
11
|
-
|
11
|
+
<% if experiment.combined? %>
|
12
|
+
<%= render 'combined_experiment', combined_experiment: experiment %>
|
13
|
+
<% else %>
|
14
|
+
<%= render 'experiment', experiment: experiment %>
|
15
|
+
<% end %>
|
12
16
|
<% end %>
|
13
17
|
</div>
|
data/config/routes.rb
CHANGED
@@ -21,7 +21,12 @@ if defined?(TrailGuide::Admin::Engine)
|
|
21
21
|
match :reset, via: [:put, :post, :get]
|
22
22
|
match :resume, via: [:put, :post, :get]
|
23
23
|
match :restart, via: [:put, :post, :get]
|
24
|
+
|
25
|
+
match :join, via: [:put, :post, :get], path: 'join/:variant'
|
26
|
+
match :leave, via: [:put, :post, :get]
|
27
|
+
|
24
28
|
match :winner, via: [:put, :post, :get], path: 'winner/:variant'
|
29
|
+
match :clear, via: [:put, :post, :get]
|
25
30
|
end
|
26
31
|
end
|
27
32
|
end
|
data/lib/trail_guide/catalog.rb
CHANGED
@@ -18,8 +18,21 @@ module TrailGuide
|
|
18
18
|
def select(name)
|
19
19
|
catalog.select(name)
|
20
20
|
end
|
21
|
+
|
22
|
+
def combined_experiment(combined, name)
|
23
|
+
experiment = Class.new(TrailGuide::CombinedExperiment)
|
24
|
+
experiment.configure combined.configuration.to_h.merge({
|
25
|
+
name: name.to_s.underscore.to_sym,
|
26
|
+
parent: combined,
|
27
|
+
combined: [],
|
28
|
+
variants: combined.configuration.variants.map { |var| Variant.new(experiment, var.name, metadata: var.metadata, weight: var.weight, control: var.control?) },
|
29
|
+
# TODO also map goals once they're separate classes
|
30
|
+
})
|
31
|
+
experiment
|
32
|
+
end
|
21
33
|
end
|
22
34
|
|
35
|
+
delegate :combined_experiment, to: :class
|
23
36
|
attr_reader :experiments
|
24
37
|
|
25
38
|
def initialize(experiments=[])
|
@@ -30,15 +43,34 @@ module TrailGuide
|
|
30
43
|
experiments.each(&block)
|
31
44
|
end
|
32
45
|
|
46
|
+
def all
|
47
|
+
experiments.map do |exp|
|
48
|
+
if exp.combined?
|
49
|
+
exp.combined.map { |name| combined_experiment(exp, name) }
|
50
|
+
else
|
51
|
+
exp
|
52
|
+
end
|
53
|
+
end.flatten
|
54
|
+
end
|
55
|
+
|
33
56
|
def find(name)
|
34
57
|
if name.is_a?(Class)
|
35
58
|
experiments.find { |exp| exp == name }
|
36
59
|
else
|
37
|
-
experiments.find do |exp|
|
60
|
+
experiment = experiments.find do |exp|
|
38
61
|
exp.experiment_name == name.to_s.underscore.to_sym ||
|
39
62
|
exp.metric == name.to_s.underscore.to_sym ||
|
40
63
|
exp.name == name.to_s.classify
|
41
64
|
end
|
65
|
+
return experiment if experiment.present?
|
66
|
+
|
67
|
+
combined = experiments.find do |exp|
|
68
|
+
next unless exp.combined?
|
69
|
+
exp.combined.any? { |combo| combo.to_s.underscore.to_sym == name.to_s.underscore.to_sym }
|
70
|
+
end
|
71
|
+
return nil unless combined.present?
|
72
|
+
|
73
|
+
return combined_experiment(combined, name)
|
42
74
|
end
|
43
75
|
end
|
44
76
|
|
@@ -46,10 +78,18 @@ module TrailGuide
|
|
46
78
|
if name.is_a?(Class)
|
47
79
|
experiments.select { |exp| exp == name }
|
48
80
|
else
|
81
|
+
# TODO we can be more efficient than mapping twice here
|
49
82
|
experiments.select do |exp|
|
50
83
|
exp.experiment_name == name.to_s.underscore.to_sym ||
|
51
84
|
exp.metric == name.to_s.underscore.to_sym ||
|
52
|
-
exp.name == name.to_s.classify
|
85
|
+
exp.name == name.to_s.classify ||
|
86
|
+
(exp.combined? && exp.combined.any? { |combo| combo.to_s.underscore.to_sym == name.to_s.underscore.to_sym })
|
87
|
+
end.map do |exp|
|
88
|
+
if exp.combined? && exp.combined.any? { |combo| combo.to_s.underscore.to_sym == name.to_s.underscore.to_sym }
|
89
|
+
combined_experiment(exp, name)
|
90
|
+
else
|
91
|
+
exp
|
92
|
+
end
|
53
93
|
end
|
54
94
|
end
|
55
95
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "trail_guide/experiments/base"
|
2
|
+
require "trail_guide/experiments/combined_config"
|
3
|
+
|
4
|
+
module TrailGuide
|
5
|
+
class CombinedExperiment < Experiments::Base
|
6
|
+
class << self
|
7
|
+
delegate :parent, to: :configuration
|
8
|
+
|
9
|
+
def configuration
|
10
|
+
@configuration ||= Experiments::CombinedConfig.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO if just I delegate on this inheriting class, will that override the
|
14
|
+
# defined methods on the base class? and will they interplay nicely? like
|
15
|
+
# with `started?` calling `started_at`, etc.?
|
16
|
+
#
|
17
|
+
# really wishing i'd written some specs right about now :-P
|
18
|
+
def start!
|
19
|
+
parent.start!
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop!
|
23
|
+
parent.stop!
|
24
|
+
end
|
25
|
+
|
26
|
+
def resume!
|
27
|
+
parent.resume!
|
28
|
+
end
|
29
|
+
|
30
|
+
def started_at
|
31
|
+
parent.started_at
|
32
|
+
end
|
33
|
+
|
34
|
+
def stopped_at
|
35
|
+
parent.stopped_at
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
delegate :parent, to: :class
|
40
|
+
delegate :running?, :started?, :started_at, :start!, to: :parent
|
41
|
+
|
42
|
+
# use the parent experiment as the algorithm and map to the matching variant
|
43
|
+
def algorithm_choose!(metadata: nil)
|
44
|
+
variant = parent.new(participant).choose!(metadata: metadata)
|
45
|
+
variants.find { |var| var == variant.name }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/trail_guide/engine.rb
CHANGED
@@ -46,6 +46,7 @@ module TrailGuide
|
|
46
46
|
config.metric = options[:metric] if options[:metric]
|
47
47
|
config.algorithm = options[:algorithm] if options[:algorithm]
|
48
48
|
config.goals = options[:goals] if options[:goals]
|
49
|
+
config.combined = options[:combined] if options[:combined]
|
49
50
|
config.reset_manually = options[:reset_manually] if options.key?(:reset_manually)
|
50
51
|
config.start_manually = options[:start_manually] if options.key?(:start_manually)
|
51
52
|
config.store_override = options[:store_override] if options.key?(:store_override)
|