Class: TrailGuide::Helper::ExperimentProxy
Instance Attribute Summary collapse
Attributes inherited from HelperProxy
#context
Instance Method Summary
collapse
-
#choose(**opts, &block) ⇒ Object
(also: #enroll)
-
#choose!(**opts, &block) ⇒ Object
(also: #enroll!)
-
#convert(checkpoint = nil, **opts, &block) ⇒ Object
-
#convert!(checkpoint = nil, **opts, &block) ⇒ Object
-
#exclude_visitor? ⇒ Boolean
-
#experiment ⇒ Object
-
#experiments ⇒ Object
-
#initialize(context, key, **opts) ⇒ ExperimentProxy
constructor
A new instance of ExperimentProxy.
-
#override_variant ⇒ Object
-
#render(prefix: nil, templates: nil, locals: {}, **opts) ⇒ Object
-
#render!(prefix: nil, templates: nil, locals: {}, **opts) ⇒ Object
-
#run(methods: nil, **opts) ⇒ Object
-
#run!(methods: nil, **opts) ⇒ Object
Methods inherited from HelperProxy
#context_type, #new, #participant
Constructor Details
#initialize(context, key, **opts) ⇒ ExperimentProxy
Returns a new instance of ExperimentProxy.
6
7
8
9
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 6
def initialize(context, key, **opts)
super(context, **opts)
@key = key.to_s.underscore.to_sym
end
|
Instance Attribute Details
#key ⇒ Object
Returns the value of attribute key.
4
5
6
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 4
def key
@key
end
|
Instance Method Details
#choose(**opts, &block) ⇒ Object
Also known as:
enroll
25
26
27
28
29
30
31
32
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 25
def choose(**opts, &block)
choose!(**opts, &block)
rescue NoExperimentsError => e
raise e
rescue => e
TrailGuide.logger.error e
experiment.control
end
|
#choose!(**opts, &block) ⇒ Object
Also known as:
enroll!
11
12
13
14
15
16
17
18
19
20
21
22
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 11
def choose!(**opts, &block)
raise NoExperimentsError, key if experiments.empty?
raise TooManyExperimentsError, "Selecting a variant requires a single experiment, but `#{key}` matches more than one experiment." if experiments.length > 1
raise TooManyExperimentsError, "Selecting a variant requires a single experiment, but `#{key}` refers to a combined experiment." if experiment.combined?
opts = {override: override_variant, excluded: exclude_visitor?}.merge(opts)
variant = experiment.choose!(**opts)
if block_given?
yield variant, opts[:metadata]
else
variant
end
end
|
#convert(checkpoint = nil, **opts, &block) ⇒ Object
126
127
128
129
130
131
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 126
def convert(checkpoint=nil, **opts, &block)
convert!(checkpoint, **opts, &block)
rescue => e
TrailGuide.logger.error e
false
end
|
#convert!(checkpoint = nil, **opts, &block) ⇒ Object
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 96
def convert!(checkpoint=nil, **opts, &block)
raise NoExperimentsError, key if experiments.empty?
checkpoints = experiments.map do |experiment|
ckpt = checkpoint || experiment.goals.find { |g| g == key }
if experiment.combined?
experiment.combined_experiments.map do |combo|
combo.convert!(ckpt, **opts)
end
else
experiment.convert!(ckpt, **opts)
end
end.flatten
return false unless checkpoints.any?
if block_given?
yield checkpoints, opts[:metadata]
else
checkpoints
end
rescue NoExperimentsError => e
unless TrailGuide.configuration.ignore_orphaned_groups?
trace = e.backtrace.find { |t| !t.match?(Regexp.new(File.dirname(__FILE__))) }
.to_s.split(Rails.root.to_s).last
.split(':').first(2).join(':')
TrailGuide.catalog.orphaned(key, trace)
end
false
end
|
#exclude_visitor? ⇒ Boolean
154
155
156
157
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 154
def exclude_visitor?
return false if experiment.configuration.skip_request_filter?
context.send(:trailguide_excluded_request?)
end
|
#experiment ⇒ Object
139
140
141
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 139
def experiment
@experiment ||= experiments.first
end
|
#experiments ⇒ Object
133
134
135
136
137
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 133
def experiments
@experiments ||= TrailGuide.catalog.select(key).map do |experiment|
experiment.new(participant)
end
end
|
#override_variant ⇒ Object
143
144
145
146
147
148
149
150
151
152
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 143
def override_variant
return unless context.respond_to?(:trailguide_params, true) || context.respond_to?(:params, true)
params = context.try(:trailguide_params) || context.try(:params)
return unless params.key?(TrailGuide.configuration.override_parameter)
experiment_params = params[TrailGuide.configuration.override_parameter]
return unless experiment_params.key?(experiment.experiment_name.to_s)
varname = experiment_params[experiment.experiment_name.to_s]
variant = experiment.variants.find { |var| var == varname }
variant.try(:name)
end
|
#render(prefix: nil, templates: nil, locals: {}, **opts) ⇒ Object
87
88
89
90
91
92
93
94
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 87
def render(prefix: nil, templates: nil, locals: {}, **opts)
render!(prefix: prefix, templates: templates, locals: locals, **opts)
rescue NoExperimentsError => e
raise e
rescue => e
TrailGuide.logger.error e
false
end
|
#render!(prefix: nil, templates: nil, locals: {}, **opts) ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 73
def render!(prefix: nil, templates: nil, locals: {}, **opts)
raise UnsupportedContextError, "The current context (#{context}) does not support rendering. Rendering is only available in controllers and views." unless context.respond_to?(:render, true)
choose!(**opts) do |variant, metadata|
locals = { variant: variant, metadata: variant.metadata }.merge(locals)
locals = { locals: locals } if context_type == :controller
template = templates[variant.name] if templates
prefix ||= (context.try(:view_context) || context).lookup_context.prefixes.first + '/' rescue ''
template ||= "#{prefix.to_s}#{variant.experiment.experiment_name.to_s.underscore}/#{variant.name.to_s.underscore}"
context.send(:render, template.to_s, **locals)
end
end
|
#run(methods: nil, **opts) ⇒ Object
64
65
66
67
68
69
70
71
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 64
def run(methods: nil, **opts)
run!(methods: methods, **opts)
rescue NoExperimentsError => e
raise e
rescue => e
TrailGuide.logger.error e
false
end
|
#run!(methods: nil, **opts) ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# File 'lib/trail_guide/helper/experiment_proxy.rb', line 35
def run!(methods: nil, **opts)
choose!(**opts) do |variant, metadata|
varmeth = methods[variant.name] if methods
varmeth ||= variant.name
unless context.respond_to?(varmeth, true)
if context_type == :controller
raise NoVariantMethodError,
"Undefined local method `#{varmeth}`. You must define a controller method matching the variant `#{variant.name}` in your experiment `#{key}`. In this case it looks like you need to define #{context.class.name}##{varmeth}(metadata={})"
elsif context_type == :template
raise NoVariantMethodError,
"Undefined local method `#{varmeth}`. You must define a helper method matching the variant `#{variant.name}` in your experiment `#{key}`. In this case it looks like you need to define ApplicationHelper##{varmeth}(metadata={})"
else
raise NoVariantMethodError,
"Undefined local method `#{varmeth}`. You must define a method matching the variant `#{variant.name}` in your experiment `#{key}`. In this case it looks like you need to define #{context.class.name}##{varmeth}(metadata={})"
end
end
arguments = context.method(varmeth).parameters
if arguments.empty?
context.send(varmeth)
elsif arguments.length > 1 || arguments[0][0] == :rest
context.send(varmeth, variant, **variant.metadata)
elsif arguments.length == 1
context.send(varmeth, **variant.metadata)
end
end
end
|