optimizely-sdk 3.6.0 → 3.9.0
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/lib/optimizely/audience.rb +18 -39
- data/lib/optimizely/bucketer.rb +35 -27
- data/lib/optimizely/condition_tree_evaluator.rb +2 -0
- data/lib/optimizely/config/datafile_project_config.rb +97 -14
- data/lib/optimizely/decide/optimizely_decide_option.rb +28 -0
- data/lib/optimizely/decide/optimizely_decision.rb +60 -0
- data/lib/optimizely/decide/optimizely_decision_message.rb +26 -0
- data/lib/optimizely/decision_service.rb +164 -141
- data/lib/optimizely/event/entity/decision.rb +6 -4
- data/lib/optimizely/event/entity/impression_event.rb +4 -2
- data/lib/optimizely/event/event_factory.rb +4 -3
- data/lib/optimizely/event/user_event_factory.rb +4 -3
- data/lib/optimizely/helpers/constants.rb +1 -0
- data/lib/optimizely/optimizely_config.rb +180 -25
- data/lib/optimizely/optimizely_user_context.rb +107 -0
- data/lib/optimizely/project_config.rb +14 -2
- data/lib/optimizely/version.rb +1 -1
- data/lib/optimizely.rb +245 -18
- metadata +7 -3
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2019, Optimizely and contributors
|
4
|
+
# Copyright 2019-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -17,19 +17,21 @@
|
|
17
17
|
#
|
18
18
|
module Optimizely
|
19
19
|
class Decision
|
20
|
-
attr_reader :campaign_id, :experiment_id, :variation_id
|
20
|
+
attr_reader :campaign_id, :experiment_id, :variation_id, :metadata
|
21
21
|
|
22
|
-
def initialize(campaign_id:, experiment_id:, variation_id:)
|
22
|
+
def initialize(campaign_id:, experiment_id:, variation_id:, metadata:)
|
23
23
|
@campaign_id = campaign_id
|
24
24
|
@experiment_id = experiment_id
|
25
25
|
@variation_id = variation_id
|
26
|
+
@metadata = metadata
|
26
27
|
end
|
27
28
|
|
28
29
|
def as_json
|
29
30
|
{
|
30
31
|
campaign_id: @campaign_id,
|
31
32
|
experiment_id: @experiment_id,
|
32
|
-
variation_id: @variation_id
|
33
|
+
variation_id: @variation_id,
|
34
|
+
metadata: @metadata
|
33
35
|
}
|
34
36
|
end
|
35
37
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2019, Optimizely and contributors
|
4
|
+
# Copyright 2019-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -19,7 +19,7 @@ require_relative 'user_event'
|
|
19
19
|
require 'optimizely/helpers/date_time_utils'
|
20
20
|
module Optimizely
|
21
21
|
class ImpressionEvent < UserEvent
|
22
|
-
attr_reader :user_id, :experiment_layer_id, :experiment_id, :variation_id,
|
22
|
+
attr_reader :user_id, :experiment_layer_id, :experiment_id, :variation_id, :metadata,
|
23
23
|
:visitor_attributes, :bot_filtering
|
24
24
|
|
25
25
|
def initialize(
|
@@ -28,6 +28,7 @@ module Optimizely
|
|
28
28
|
experiment_layer_id:,
|
29
29
|
experiment_id:,
|
30
30
|
variation_id:,
|
31
|
+
metadata:,
|
31
32
|
visitor_attributes:,
|
32
33
|
bot_filtering:
|
33
34
|
)
|
@@ -38,6 +39,7 @@ module Optimizely
|
|
38
39
|
@experiment_layer_id = experiment_layer_id
|
39
40
|
@experiment_id = experiment_id
|
40
41
|
@variation_id = variation_id
|
42
|
+
@metadata = metadata
|
41
43
|
@visitor_attributes = visitor_attributes
|
42
44
|
@bot_filtering = bot_filtering
|
43
45
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2019, Optimizely and contributors
|
4
|
+
# Copyright 2019-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -101,10 +101,11 @@ module Optimizely
|
|
101
101
|
private
|
102
102
|
|
103
103
|
def create_impression_event_visitor(impression_event)
|
104
|
-
decision =
|
104
|
+
decision = Decision.new(
|
105
105
|
campaign_id: impression_event.experiment_layer_id,
|
106
106
|
experiment_id: impression_event.experiment_id,
|
107
|
-
variation_id: impression_event.variation_id
|
107
|
+
variation_id: impression_event.variation_id,
|
108
|
+
metadata: impression_event.metadata
|
108
109
|
)
|
109
110
|
|
110
111
|
snapshot_event = Optimizely::SnapshotEvent.new(
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2019, Optimizely and contributors
|
4
|
+
# Copyright 2019-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -22,7 +22,7 @@ require_relative 'event_factory'
|
|
22
22
|
module Optimizely
|
23
23
|
class UserEventFactory
|
24
24
|
# UserEventFactory builds ImpressionEvent and ConversionEvent objects from a given user_event.
|
25
|
-
def self.create_impression_event(project_config, experiment, variation_id, user_id, user_attributes)
|
25
|
+
def self.create_impression_event(project_config, experiment, variation_id, metadata, user_id, user_attributes)
|
26
26
|
# Create impression Event to be sent to the logging endpoint.
|
27
27
|
#
|
28
28
|
# project_config - Instance of ProjectConfig
|
@@ -42,13 +42,14 @@ module Optimizely
|
|
42
42
|
).as_json
|
43
43
|
|
44
44
|
visitor_attributes = Optimizely::EventFactory.build_attribute_list(user_attributes, project_config)
|
45
|
-
experiment_layer_id =
|
45
|
+
experiment_layer_id = experiment['layerId']
|
46
46
|
Optimizely::ImpressionEvent.new(
|
47
47
|
event_context: event_context,
|
48
48
|
user_id: user_id,
|
49
49
|
experiment_layer_id: experiment_layer_id,
|
50
50
|
experiment_id: experiment['id'],
|
51
51
|
variation_id: variation_id,
|
52
|
+
metadata: metadata,
|
52
53
|
visitor_attributes: visitor_attributes,
|
53
54
|
bot_filtering: project_config.bot_filtering
|
54
55
|
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019-
|
3
|
+
# Copyright 2019-2021, Optimizely and contributors
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -16,53 +16,109 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
module Optimizely
|
19
|
+
require 'json'
|
19
20
|
class OptimizelyConfig
|
21
|
+
include Optimizely::ConditionTreeEvaluator
|
20
22
|
def initialize(project_config)
|
21
23
|
@project_config = project_config
|
24
|
+
@rollouts = @project_config.rollouts
|
25
|
+
@audiences = []
|
26
|
+
audience_id_lookup_dict = {}
|
27
|
+
|
28
|
+
@project_config.typed_audiences.each do |typed_audience|
|
29
|
+
@audiences.push(
|
30
|
+
'id' => typed_audience['id'],
|
31
|
+
'name' => typed_audience['name'],
|
32
|
+
'conditions' => typed_audience['conditions'].to_json
|
33
|
+
)
|
34
|
+
audience_id_lookup_dict[typed_audience['id']] = typed_audience['id']
|
35
|
+
end
|
36
|
+
|
37
|
+
@project_config.audiences.each do |audience|
|
38
|
+
next unless !audience_id_lookup_dict.key?(audience['id']) && (audience['id'] != '$opt_dummy_audience')
|
39
|
+
|
40
|
+
@audiences.push(
|
41
|
+
'id' => audience['id'],
|
42
|
+
'name' => audience['name'],
|
43
|
+
'conditions' => audience['conditions']
|
44
|
+
)
|
45
|
+
end
|
22
46
|
end
|
23
47
|
|
24
48
|
def config
|
25
49
|
experiments_map_object = experiments_map
|
26
|
-
features_map = get_features_map(
|
27
|
-
{
|
50
|
+
features_map = get_features_map(experiments_id_map)
|
51
|
+
config = {
|
52
|
+
'sdkKey' => @project_config.sdk_key,
|
28
53
|
'datafile' => @project_config.datafile,
|
54
|
+
# This experimentsMap is for experiments of legacy projects only.
|
55
|
+
# For flag projects, experiment keys are not guaranteed to be unique
|
56
|
+
# across multiple flags, so this map may not include all experiments
|
57
|
+
# when keys conflict. Use experimentRules and deliveryRules instead.
|
29
58
|
'experimentsMap' => experiments_map_object,
|
30
59
|
'featuresMap' => features_map,
|
31
|
-
'revision' => @project_config.revision
|
60
|
+
'revision' => @project_config.revision,
|
61
|
+
'attributes' => get_attributes_list(@project_config.attributes),
|
62
|
+
'audiences' => @audiences,
|
63
|
+
'events' => get_events_list(@project_config.events),
|
64
|
+
'environmentKey' => @project_config.environment_key
|
32
65
|
}
|
66
|
+
config
|
33
67
|
end
|
34
68
|
|
35
69
|
private
|
36
70
|
|
37
|
-
def
|
38
|
-
feature_variables_map =
|
39
|
-
|
40
|
-
end
|
71
|
+
def experiments_id_map
|
72
|
+
feature_variables_map = feature_variable_map
|
73
|
+
audiences_id_map = audiences_map
|
41
74
|
@project_config.experiments.reduce({}) do |experiments_map, experiment|
|
75
|
+
feature_id = @project_config.experiment_feature_map.fetch(experiment['id'], []).first
|
42
76
|
experiments_map.update(
|
43
|
-
experiment['
|
77
|
+
experiment['id'] => {
|
44
78
|
'id' => experiment['id'],
|
45
79
|
'key' => experiment['key'],
|
46
|
-
'variationsMap' =>
|
47
|
-
|
48
|
-
'id' => variation['id'],
|
49
|
-
'key' => variation['key'],
|
50
|
-
'variablesMap' => get_merged_variables_map(variation, experiment['id'], feature_variables_map)
|
51
|
-
}
|
52
|
-
variation_object['featureEnabled'] = variation['featureEnabled'] if @project_config.feature_experiment?(experiment['id'])
|
53
|
-
variations_map.update(variation['key'] => variation_object)
|
54
|
-
end
|
80
|
+
'variationsMap' => get_variation_map(feature_id, experiment, feature_variables_map),
|
81
|
+
'audiences' => replace_ids_with_names(experiment.fetch('audienceConditions', []), audiences_id_map) || ''
|
55
82
|
}
|
56
83
|
)
|
57
84
|
end
|
58
85
|
end
|
59
86
|
|
87
|
+
def audiences_map
|
88
|
+
@audiences.reduce({}) do |audiences_map, optly_audience|
|
89
|
+
audiences_map.update(optly_audience['id'] => optly_audience['name'])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def experiments_map
|
94
|
+
experiments_id_map.values.reduce({}) do |experiments_key_map, experiment|
|
95
|
+
experiments_key_map.update(experiment['key'] => experiment)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def feature_variable_map
|
100
|
+
@project_config.feature_flags.reduce({}) do |result_map, feature|
|
101
|
+
result_map.update(feature['id'] => feature['variables'])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_variation_map(feature_id, experiment, feature_variables_map)
|
106
|
+
experiment['variations'].reduce({}) do |variations_map, variation|
|
107
|
+
variation_object = {
|
108
|
+
'id' => variation['id'],
|
109
|
+
'key' => variation['key'],
|
110
|
+
'featureEnabled' => variation['featureEnabled'],
|
111
|
+
'variablesMap' => get_merged_variables_map(variation, feature_id, feature_variables_map)
|
112
|
+
}
|
113
|
+
variations_map.update(variation['key'] => variation_object)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
60
117
|
# Merges feature key and type from feature variables to variation variables.
|
61
|
-
def get_merged_variables_map(variation,
|
62
|
-
|
63
|
-
return {} unless feature_ids
|
118
|
+
def get_merged_variables_map(variation, feature_id, feature_variables_map)
|
119
|
+
return {} unless feature_id
|
64
120
|
|
65
|
-
|
121
|
+
feature_variables = feature_variables_map[feature_id]
|
66
122
|
# temporary variation variables map to get values to merge.
|
67
123
|
temp_variables_id_map = {}
|
68
124
|
if variation['variables']
|
@@ -75,7 +131,7 @@ module Optimizely
|
|
75
131
|
)
|
76
132
|
end
|
77
133
|
end
|
78
|
-
|
134
|
+
feature_variables.reduce({}) do |variables_map, feature_variable|
|
79
135
|
variation_variable = temp_variables_id_map[feature_variable['id']]
|
80
136
|
variable_value = variation['featureEnabled'] && variation_variable ? variation_variable['value'] : feature_variable['defaultValue']
|
81
137
|
variables_map.update(
|
@@ -91,13 +147,15 @@ module Optimizely
|
|
91
147
|
|
92
148
|
def get_features_map(all_experiments_map)
|
93
149
|
@project_config.feature_flags.reduce({}) do |features_map, feature|
|
150
|
+
delivery_rules = get_delivery_rules(@rollouts, feature['rolloutId'], feature['id'])
|
94
151
|
features_map.update(
|
95
152
|
feature['key'] => {
|
96
153
|
'id' => feature['id'],
|
97
154
|
'key' => feature['key'],
|
155
|
+
# This experimentsMap is deprecated. Use experimentRules and deliveryRules instead.
|
98
156
|
'experimentsMap' => feature['experimentIds'].reduce({}) do |experiments_map, experiment_id|
|
99
157
|
experiment_key = @project_config.experiment_id_map[experiment_id]['key']
|
100
|
-
experiments_map.update(experiment_key =>
|
158
|
+
experiments_map.update(experiment_key => experiments_id_map[experiment_id])
|
101
159
|
end,
|
102
160
|
'variablesMap' => feature['variables'].reduce({}) do |variables, variable|
|
103
161
|
variables.update(
|
@@ -108,10 +166,107 @@ module Optimizely
|
|
108
166
|
'value' => variable['defaultValue']
|
109
167
|
}
|
110
168
|
)
|
111
|
-
end
|
169
|
+
end,
|
170
|
+
'experimentRules' => feature['experimentIds'].reduce([]) do |experiments_map, experiment_id|
|
171
|
+
experiments_map.push(all_experiments_map[experiment_id])
|
172
|
+
end,
|
173
|
+
'deliveryRules' => delivery_rules
|
112
174
|
}
|
113
175
|
)
|
114
176
|
end
|
115
177
|
end
|
178
|
+
|
179
|
+
def get_attributes_list(attributes)
|
180
|
+
attributes.map do |attribute|
|
181
|
+
{
|
182
|
+
'id' => attribute['id'],
|
183
|
+
'key' => attribute['key']
|
184
|
+
}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def get_events_list(events)
|
189
|
+
events.map do |event|
|
190
|
+
{
|
191
|
+
'id' => event['id'],
|
192
|
+
'key' => event['key'],
|
193
|
+
'experimentIds' => event['experimentIds']
|
194
|
+
}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def lookup_name_from_id(audience_id, audiences_map)
|
199
|
+
audiences_map[audience_id] || audience_id
|
200
|
+
end
|
201
|
+
|
202
|
+
def stringify_conditions(conditions, audiences_map)
|
203
|
+
operand = 'OR'
|
204
|
+
conditions_str = ''
|
205
|
+
length = conditions.length()
|
206
|
+
return '' if length.zero?
|
207
|
+
return '"' + lookup_name_from_id(conditions[0], audiences_map) + '"' if length == 1 && !OPERATORS.include?(conditions[0])
|
208
|
+
|
209
|
+
# Edge cases for lengths 0, 1 or 2
|
210
|
+
if length == 2 && OPERATORS.include?(conditions[0]) && !conditions[1].is_a?(Array) && !OPERATORS.include?(conditions[1])
|
211
|
+
return '"' + lookup_name_from_id(conditions[1], audiences_map) + '"' if conditions[0] != 'not'
|
212
|
+
|
213
|
+
return conditions[0].upcase + ' "' + lookup_name_from_id(conditions[1], audiences_map) + '"'
|
214
|
+
|
215
|
+
end
|
216
|
+
if length > 1
|
217
|
+
(0..length - 1).each do |n|
|
218
|
+
# Operand is handled here and made Upper Case
|
219
|
+
if OPERATORS.include?(conditions[n])
|
220
|
+
operand = conditions[n].upcase
|
221
|
+
# Check if element is a list or not
|
222
|
+
elsif conditions[n].is_a?(Array)
|
223
|
+
# Check if at the end or not to determine where to add the operand
|
224
|
+
# Recursive call to call stringify on embedded list
|
225
|
+
conditions_str += if n + 1 < length
|
226
|
+
'(' + stringify_conditions(conditions[n], audiences_map) + ') '
|
227
|
+
else
|
228
|
+
operand + ' (' + stringify_conditions(conditions[n], audiences_map) + ')'
|
229
|
+
end
|
230
|
+
# If the item is not a list, we process as an audience ID and retrieve the name
|
231
|
+
else
|
232
|
+
audience_name = lookup_name_from_id(conditions[n], audiences_map)
|
233
|
+
unless audience_name.nil?
|
234
|
+
# Below handles all cases for one ID or greater
|
235
|
+
conditions_str += if n + 1 < length - 1
|
236
|
+
'"' + audience_name + '" ' + operand + ' '
|
237
|
+
elsif n + 1 == length
|
238
|
+
operand + ' "' + audience_name + '"'
|
239
|
+
else
|
240
|
+
'"' + audience_name + '" '
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
conditions_str || ''
|
247
|
+
end
|
248
|
+
|
249
|
+
def replace_ids_with_names(conditions, audiences_map)
|
250
|
+
!conditions.empty? ? stringify_conditions(conditions, audiences_map) : ''
|
251
|
+
end
|
252
|
+
|
253
|
+
def get_delivery_rules(rollouts, rollout_id, feature_id)
|
254
|
+
audiences_id_map = audiences_map
|
255
|
+
feature_variables_map = feature_variable_map
|
256
|
+
rollout = rollouts.select { |selected_rollout| selected_rollout['id'] == rollout_id }
|
257
|
+
if rollout.any?
|
258
|
+
rollout = rollout[0]
|
259
|
+
experiments = rollout['experiments']
|
260
|
+
return experiments.map do |experiment|
|
261
|
+
{
|
262
|
+
'id' => experiment['id'],
|
263
|
+
'key' => experiment['key'],
|
264
|
+
'variationsMap' => get_variation_map(feature_id, experiment, feature_variables_map),
|
265
|
+
'audiences' => replace_ids_with_names(experiment.fetch('audienceConditions', []), audiences_id_map) || ''
|
266
|
+
}
|
267
|
+
end
|
268
|
+
end
|
269
|
+
[]
|
270
|
+
end
|
116
271
|
end
|
117
272
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright 2020, Optimizely and contributors
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'json'
|
20
|
+
|
21
|
+
module Optimizely
|
22
|
+
class OptimizelyUserContext
|
23
|
+
# Representation of an Optimizely User Context using which APIs are to be called.
|
24
|
+
|
25
|
+
attr_reader :user_id
|
26
|
+
|
27
|
+
def initialize(optimizely_client, user_id, user_attributes)
|
28
|
+
@attr_mutex = Mutex.new
|
29
|
+
@optimizely_client = optimizely_client
|
30
|
+
@user_id = user_id
|
31
|
+
@user_attributes = user_attributes.nil? ? {} : user_attributes.clone
|
32
|
+
end
|
33
|
+
|
34
|
+
def clone
|
35
|
+
OptimizelyUserContext.new(@optimizely_client, @user_id, user_attributes)
|
36
|
+
end
|
37
|
+
|
38
|
+
def user_attributes
|
39
|
+
@attr_mutex.synchronize { @user_attributes.clone }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set an attribute for a given key
|
43
|
+
#
|
44
|
+
# @param key - An attribute key
|
45
|
+
# @param value - An attribute value
|
46
|
+
|
47
|
+
def set_attribute(attribute_key, attribute_value)
|
48
|
+
@attr_mutex.synchronize { @user_attributes[attribute_key] = attribute_value }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a decision result (OptimizelyDecision) for a given flag key and a user context, which contains all data required to deliver the flag.
|
52
|
+
#
|
53
|
+
# If the SDK finds an error, it'll return a `decision` with nil for `variation_key`. The decision will include an error message in `reasons`
|
54
|
+
#
|
55
|
+
# @param key -A flag key for which a decision will be made
|
56
|
+
# @param options - A list of options for decision making.
|
57
|
+
#
|
58
|
+
# @return [OptimizelyDecision] A decision result
|
59
|
+
|
60
|
+
def decide(key, options = nil)
|
61
|
+
@optimizely_client&.decide(clone, key, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns a hash of decision results (OptimizelyDecision) for multiple flag keys and a user context.
|
65
|
+
#
|
66
|
+
# If the SDK finds an error for a key, the response will include a decision for the key showing `reasons` for the error.
|
67
|
+
# The SDK will always return hash of decisions. When it can not process requests, it'll return an empty hash after logging the errors.
|
68
|
+
#
|
69
|
+
# @param keys - A list of flag keys for which the decisions will be made.
|
70
|
+
# @param options - A list of options for decision making.
|
71
|
+
#
|
72
|
+
# @return - Hash of decisions containing flag keys as hash keys and corresponding decisions as their values.
|
73
|
+
|
74
|
+
def decide_for_keys(keys, options = nil)
|
75
|
+
@optimizely_client&.decide_for_keys(clone, keys, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a hash of decision results (OptimizelyDecision) for all active flag keys.
|
79
|
+
#
|
80
|
+
# @param options - A list of options for decision making.
|
81
|
+
#
|
82
|
+
# @return - Hash of decisions containing flag keys as hash keys and corresponding decisions as their values.
|
83
|
+
|
84
|
+
def decide_all(options = nil)
|
85
|
+
@optimizely_client&.decide_all(clone, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Track an event
|
89
|
+
#
|
90
|
+
# @param event_key - Event key representing the event which needs to be recorded.
|
91
|
+
|
92
|
+
def track_event(event_key, event_tags = nil)
|
93
|
+
@optimizely_client&.track(event_key, @user_id, user_attributes, event_tags)
|
94
|
+
end
|
95
|
+
|
96
|
+
def as_json
|
97
|
+
{
|
98
|
+
user_id: @user_id,
|
99
|
+
attributes: @user_attributes
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_json(*args)
|
104
|
+
as_json.to_json(*args)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|