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,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2016-
|
3
|
+
# Copyright 2016-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.
|
@@ -46,12 +46,20 @@ module Optimizely
|
|
46
46
|
|
47
47
|
def revision; end
|
48
48
|
|
49
|
+
def sdk_key; end
|
50
|
+
|
51
|
+
def environment_key; end
|
52
|
+
|
53
|
+
def send_flag_decisions; end
|
54
|
+
|
49
55
|
def rollouts; end
|
50
56
|
|
51
57
|
def experiment_running?(experiment); end
|
52
58
|
|
53
59
|
def get_experiment_from_key(experiment_key); end
|
54
60
|
|
61
|
+
def get_experiment_from_id(experiment_id); end
|
62
|
+
|
55
63
|
def get_experiment_key(experiment_id); end
|
56
64
|
|
57
65
|
def get_event_from_key(event_key); end
|
@@ -60,9 +68,13 @@ module Optimizely
|
|
60
68
|
|
61
69
|
def get_variation_from_id(experiment_key, variation_id); end
|
62
70
|
|
71
|
+
def get_variation_from_id_by_experiment_id(experiment_id, variation_id); end
|
72
|
+
|
73
|
+
def get_variation_id_from_key_by_experiment_id(experiment_id, variation_key); end
|
74
|
+
|
63
75
|
def get_variation_id_from_key(experiment_key, variation_key); end
|
64
76
|
|
65
|
-
def get_whitelisted_variations(
|
77
|
+
def get_whitelisted_variations(experiment_id); end
|
66
78
|
|
67
79
|
def get_attribute_id(attribute_key); end
|
68
80
|
|
data/lib/optimizely/version.rb
CHANGED
data/lib/optimizely.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-
|
4
|
+
# Copyright 2016-2021, 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,6 +19,9 @@ require_relative 'optimizely/audience'
|
|
19
19
|
require_relative 'optimizely/config/datafile_project_config'
|
20
20
|
require_relative 'optimizely/config_manager/http_project_config_manager'
|
21
21
|
require_relative 'optimizely/config_manager/static_project_config_manager'
|
22
|
+
require_relative 'optimizely/decide/optimizely_decide_option'
|
23
|
+
require_relative 'optimizely/decide/optimizely_decision'
|
24
|
+
require_relative 'optimizely/decide/optimizely_decision_message'
|
22
25
|
require_relative 'optimizely/decision_service'
|
23
26
|
require_relative 'optimizely/error_handler'
|
24
27
|
require_relative 'optimizely/event_builder'
|
@@ -34,9 +37,12 @@ require_relative 'optimizely/helpers/variable_type'
|
|
34
37
|
require_relative 'optimizely/logger'
|
35
38
|
require_relative 'optimizely/notification_center'
|
36
39
|
require_relative 'optimizely/optimizely_config'
|
40
|
+
require_relative 'optimizely/optimizely_user_context'
|
37
41
|
|
38
42
|
module Optimizely
|
39
43
|
class Project
|
44
|
+
include Optimizely::Decide
|
45
|
+
|
40
46
|
attr_reader :notification_center
|
41
47
|
# @api no-doc
|
42
48
|
attr_reader :config_manager, :decision_service, :error_handler, :event_dispatcher,
|
@@ -67,12 +73,21 @@ module Optimizely
|
|
67
73
|
sdk_key = nil,
|
68
74
|
config_manager = nil,
|
69
75
|
notification_center = nil,
|
70
|
-
event_processor = nil
|
76
|
+
event_processor = nil,
|
77
|
+
default_decide_options = []
|
71
78
|
)
|
72
79
|
@logger = logger || NoOpLogger.new
|
73
80
|
@error_handler = error_handler || NoOpErrorHandler.new
|
74
81
|
@event_dispatcher = event_dispatcher || EventDispatcher.new(logger: @logger, error_handler: @error_handler)
|
75
82
|
@user_profile_service = user_profile_service
|
83
|
+
@default_decide_options = []
|
84
|
+
|
85
|
+
if default_decide_options.is_a? Array
|
86
|
+
@default_decide_options = default_decide_options.clone
|
87
|
+
else
|
88
|
+
@logger.log(Logger::DEBUG, 'Provided default decide options is not an array.')
|
89
|
+
@default_decide_options = []
|
90
|
+
end
|
76
91
|
|
77
92
|
begin
|
78
93
|
validate_instantiation_options
|
@@ -107,6 +122,175 @@ module Optimizely
|
|
107
122
|
end
|
108
123
|
end
|
109
124
|
|
125
|
+
# Create a context of the user for which decision APIs will be called.
|
126
|
+
#
|
127
|
+
# A user context will be created successfully even when the SDK is not fully configured yet.
|
128
|
+
#
|
129
|
+
# @param user_id - The user ID to be used for bucketing.
|
130
|
+
# @param attributes - A Hash representing user attribute names and values.
|
131
|
+
#
|
132
|
+
# @return [OptimizelyUserContext] An OptimizelyUserContext associated with this OptimizelyClient.
|
133
|
+
# @return [nil] If user attributes are not in valid format.
|
134
|
+
|
135
|
+
def create_user_context(user_id, attributes = nil)
|
136
|
+
# We do not check for is_valid here as a user context can be created successfully
|
137
|
+
# even when the SDK is not fully configured.
|
138
|
+
|
139
|
+
# validate user_id
|
140
|
+
return nil unless Optimizely::Helpers::Validator.inputs_valid?(
|
141
|
+
{
|
142
|
+
user_id: user_id
|
143
|
+
}, @logger, Logger::ERROR
|
144
|
+
)
|
145
|
+
|
146
|
+
# validate attributes
|
147
|
+
return nil unless user_inputs_valid?(attributes)
|
148
|
+
|
149
|
+
user_context = OptimizelyUserContext.new(self, user_id, attributes)
|
150
|
+
user_context
|
151
|
+
end
|
152
|
+
|
153
|
+
def decide(user_context, key, decide_options = [])
|
154
|
+
# raising on user context as it is internal and not provided directly by the user.
|
155
|
+
raise if user_context.class != OptimizelyUserContext
|
156
|
+
|
157
|
+
reasons = []
|
158
|
+
|
159
|
+
# check if SDK is ready
|
160
|
+
unless is_valid
|
161
|
+
@logger.log(Logger::ERROR, InvalidProjectConfigError.new('decide').message)
|
162
|
+
reasons.push(OptimizelyDecisionMessage::SDK_NOT_READY)
|
163
|
+
return OptimizelyDecision.new(flag_key: key, user_context: user_context, reasons: reasons)
|
164
|
+
end
|
165
|
+
|
166
|
+
# validate that key is a string
|
167
|
+
unless key.is_a?(String)
|
168
|
+
@logger.log(Logger::ERROR, 'Provided key is invalid')
|
169
|
+
reasons.push(format(OptimizelyDecisionMessage::FLAG_KEY_INVALID, key))
|
170
|
+
return OptimizelyDecision.new(flag_key: key, user_context: user_context, reasons: reasons)
|
171
|
+
end
|
172
|
+
|
173
|
+
# validate that key maps to a feature flag
|
174
|
+
config = project_config
|
175
|
+
feature_flag = config.get_feature_flag_from_key(key)
|
176
|
+
unless feature_flag
|
177
|
+
@logger.log(Logger::ERROR, "No feature flag was found for key '#{key}'.")
|
178
|
+
reasons.push(format(OptimizelyDecisionMessage::FLAG_KEY_INVALID, key))
|
179
|
+
return OptimizelyDecision.new(flag_key: key, user_context: user_context, reasons: reasons)
|
180
|
+
end
|
181
|
+
|
182
|
+
# merge decide_options and default_decide_options
|
183
|
+
if decide_options.is_a? Array
|
184
|
+
decide_options += @default_decide_options
|
185
|
+
else
|
186
|
+
@logger.log(Logger::DEBUG, 'Provided decide options is not an array. Using default decide options.')
|
187
|
+
decide_options = @default_decide_options
|
188
|
+
end
|
189
|
+
|
190
|
+
# Create Optimizely Decision Result.
|
191
|
+
user_id = user_context.user_id
|
192
|
+
attributes = user_context.user_attributes
|
193
|
+
variation_key = nil
|
194
|
+
feature_enabled = false
|
195
|
+
rule_key = nil
|
196
|
+
flag_key = key
|
197
|
+
all_variables = {}
|
198
|
+
decision_event_dispatched = false
|
199
|
+
experiment = nil
|
200
|
+
decision_source = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
201
|
+
|
202
|
+
decision, reasons_received = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes, decide_options)
|
203
|
+
reasons.push(*reasons_received)
|
204
|
+
|
205
|
+
# Send impression event if Decision came from a feature test and decide options doesn't include disableDecisionEvent
|
206
|
+
if decision.is_a?(Optimizely::DecisionService::Decision)
|
207
|
+
experiment = decision.experiment
|
208
|
+
rule_key = experiment['key']
|
209
|
+
variation = decision['variation']
|
210
|
+
variation_key = variation['key']
|
211
|
+
feature_enabled = variation['featureEnabled']
|
212
|
+
decision_source = decision.source
|
213
|
+
end
|
214
|
+
|
215
|
+
unless decide_options.include? OptimizelyDecideOption::DISABLE_DECISION_EVENT
|
216
|
+
if decision_source == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST'] || config.send_flag_decisions
|
217
|
+
send_impression(config, experiment, variation_key || '', flag_key, rule_key || '', feature_enabled, decision_source, user_id, attributes)
|
218
|
+
decision_event_dispatched = true
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Generate all variables map if decide options doesn't include excludeVariables
|
223
|
+
unless decide_options.include? OptimizelyDecideOption::EXCLUDE_VARIABLES
|
224
|
+
feature_flag['variables'].each do |variable|
|
225
|
+
variable_value = get_feature_variable_for_variation(key, feature_enabled, variation, variable, user_id)
|
226
|
+
all_variables[variable['key']] = Helpers::VariableType.cast_value_to_type(variable_value, variable['type'], @logger)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
should_include_reasons = decide_options.include? OptimizelyDecideOption::INCLUDE_REASONS
|
231
|
+
|
232
|
+
# Send notification
|
233
|
+
@notification_center.send_notifications(
|
234
|
+
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
235
|
+
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FLAG'],
|
236
|
+
user_id, (attributes || {}),
|
237
|
+
flag_key: flag_key,
|
238
|
+
enabled: feature_enabled,
|
239
|
+
variables: all_variables,
|
240
|
+
variation_key: variation_key,
|
241
|
+
rule_key: rule_key,
|
242
|
+
reasons: should_include_reasons ? reasons : [],
|
243
|
+
decision_event_dispatched: decision_event_dispatched
|
244
|
+
)
|
245
|
+
|
246
|
+
OptimizelyDecision.new(
|
247
|
+
variation_key: variation_key,
|
248
|
+
enabled: feature_enabled,
|
249
|
+
variables: all_variables,
|
250
|
+
rule_key: rule_key,
|
251
|
+
flag_key: flag_key,
|
252
|
+
user_context: user_context,
|
253
|
+
reasons: should_include_reasons ? reasons : []
|
254
|
+
)
|
255
|
+
end
|
256
|
+
|
257
|
+
def decide_all(user_context, decide_options = [])
|
258
|
+
# raising on user context as it is internal and not provided directly by the user.
|
259
|
+
raise if user_context.class != OptimizelyUserContext
|
260
|
+
|
261
|
+
# check if SDK is ready
|
262
|
+
unless is_valid
|
263
|
+
@logger.log(Logger::ERROR, InvalidProjectConfigError.new('decide_all').message)
|
264
|
+
return {}
|
265
|
+
end
|
266
|
+
|
267
|
+
keys = []
|
268
|
+
project_config.feature_flags.each do |feature_flag|
|
269
|
+
keys.push(feature_flag['key'])
|
270
|
+
end
|
271
|
+
decide_for_keys(user_context, keys, decide_options)
|
272
|
+
end
|
273
|
+
|
274
|
+
def decide_for_keys(user_context, keys, decide_options = [])
|
275
|
+
# raising on user context as it is internal and not provided directly by the user.
|
276
|
+
raise if user_context.class != OptimizelyUserContext
|
277
|
+
|
278
|
+
# check if SDK is ready
|
279
|
+
unless is_valid
|
280
|
+
@logger.log(Logger::ERROR, InvalidProjectConfigError.new('decide_for_keys').message)
|
281
|
+
return {}
|
282
|
+
end
|
283
|
+
|
284
|
+
enabled_flags_only = (!decide_options.nil? && (decide_options.include? OptimizelyDecideOption::ENABLED_FLAGS_ONLY)) || (@default_decide_options.include? OptimizelyDecideOption::ENABLED_FLAGS_ONLY)
|
285
|
+
|
286
|
+
decisions = {}
|
287
|
+
keys.each do |key|
|
288
|
+
decision = decide(user_context, key, decide_options)
|
289
|
+
decisions[key] = decision unless enabled_flags_only && !decision.enabled
|
290
|
+
end
|
291
|
+
decisions
|
292
|
+
end
|
293
|
+
|
110
294
|
# Buckets visitor and sends impression event to Optimizely.
|
111
295
|
#
|
112
296
|
# @param experiment_key - Experiment which needs to be activated.
|
@@ -140,7 +324,10 @@ module Optimizely
|
|
140
324
|
|
141
325
|
# Create and dispatch impression event
|
142
326
|
experiment = config.get_experiment_from_key(experiment_key)
|
143
|
-
send_impression(
|
327
|
+
send_impression(
|
328
|
+
config, experiment, variation_key, '', experiment_key, true,
|
329
|
+
Optimizely::DecisionService::DECISION_SOURCES['EXPERIMENT'], user_id, attributes
|
330
|
+
)
|
144
331
|
|
145
332
|
variation_key
|
146
333
|
end
|
@@ -219,7 +406,7 @@ module Optimizely
|
|
219
406
|
config = project_config
|
220
407
|
|
221
408
|
forced_variation_key = nil
|
222
|
-
forced_variation = @decision_service.get_forced_variation(config, experiment_key, user_id)
|
409
|
+
forced_variation, = @decision_service.get_forced_variation(config, experiment_key, user_id)
|
223
410
|
forced_variation_key = forced_variation['key'] if forced_variation
|
224
411
|
|
225
412
|
forced_variation_key
|
@@ -303,7 +490,7 @@ module Optimizely
|
|
303
490
|
return false
|
304
491
|
end
|
305
492
|
|
306
|
-
decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
493
|
+
decision, = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
307
494
|
|
308
495
|
feature_enabled = false
|
309
496
|
source_string = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
@@ -316,14 +503,23 @@ module Optimizely
|
|
316
503
|
experiment_key: decision.experiment['key'],
|
317
504
|
variation_key: variation['key']
|
318
505
|
}
|
319
|
-
# Send event if Decision came from
|
320
|
-
send_impression(
|
321
|
-
|
322
|
-
|
323
|
-
|
506
|
+
# Send event if Decision came from a feature test.
|
507
|
+
send_impression(
|
508
|
+
config, decision.experiment, variation['key'], feature_flag_key, decision.experiment['key'], feature_enabled, source_string, user_id, attributes
|
509
|
+
)
|
510
|
+
elsif decision.source == Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT'] && config.send_flag_decisions
|
511
|
+
send_impression(
|
512
|
+
config, decision.experiment, variation['key'], feature_flag_key, decision.experiment['key'], feature_enabled, source_string, user_id, attributes
|
513
|
+
)
|
324
514
|
end
|
325
515
|
end
|
326
516
|
|
517
|
+
if decision.nil? && config.send_flag_decisions
|
518
|
+
send_impression(
|
519
|
+
config, nil, '', feature_flag_key, '', feature_enabled, source_string, user_id, attributes
|
520
|
+
)
|
521
|
+
end
|
522
|
+
|
327
523
|
@notification_center.send_notifications(
|
328
524
|
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
329
525
|
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FEATURE'],
|
@@ -543,7 +739,7 @@ module Optimizely
|
|
543
739
|
return nil
|
544
740
|
end
|
545
741
|
|
546
|
-
decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
742
|
+
decision, = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
547
743
|
variation = decision ? decision['variation'] : nil
|
548
744
|
feature_enabled = variation ? variation['featureEnabled'] : false
|
549
745
|
all_variables = {}
|
@@ -681,12 +877,14 @@ module Optimizely
|
|
681
877
|
experiment = config.get_experiment_from_key(experiment_key)
|
682
878
|
return nil if experiment.nil?
|
683
879
|
|
880
|
+
experiment_id = experiment['id']
|
881
|
+
|
684
882
|
return nil unless user_inputs_valid?(attributes)
|
685
883
|
|
686
|
-
variation_id = @decision_service.get_variation(config,
|
884
|
+
variation_id, = @decision_service.get_variation(config, experiment_id, user_id, attributes)
|
687
885
|
variation = config.get_variation_from_id(experiment_key, variation_id) unless variation_id.nil?
|
688
886
|
variation_key = variation['key'] if variation
|
689
|
-
decision_notification_type = if config.feature_experiment?(
|
887
|
+
decision_notification_type = if config.feature_experiment?(experiment_id)
|
690
888
|
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FEATURE_TEST']
|
691
889
|
else
|
692
890
|
Helpers::Constants::DECISION_NOTIFICATION_TYPES['AB_TEST']
|
@@ -749,7 +947,7 @@ module Optimizely
|
|
749
947
|
return nil
|
750
948
|
end
|
751
949
|
|
752
|
-
decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
950
|
+
decision, = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
753
951
|
variation = decision ? decision['variation'] : nil
|
754
952
|
feature_enabled = variation ? variation['featureEnabled'] : false
|
755
953
|
|
@@ -867,15 +1065,44 @@ module Optimizely
|
|
867
1065
|
raise InvalidInputError, 'event_dispatcher'
|
868
1066
|
end
|
869
1067
|
|
870
|
-
def send_impression(config, experiment, variation_key, user_id, attributes = nil)
|
1068
|
+
def send_impression(config, experiment, variation_key, flag_key, rule_key, enabled, rule_type, user_id, attributes = nil)
|
1069
|
+
if experiment.nil?
|
1070
|
+
experiment = {
|
1071
|
+
'id' => '',
|
1072
|
+
'key' => '',
|
1073
|
+
'layerId' => '',
|
1074
|
+
'status' => '',
|
1075
|
+
'variations' => [],
|
1076
|
+
'trafficAllocation' => [],
|
1077
|
+
'audienceIds' => [],
|
1078
|
+
'audienceConditions' => [],
|
1079
|
+
'forcedVariations' => {}
|
1080
|
+
}
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
experiment_id = experiment['id']
|
871
1084
|
experiment_key = experiment['key']
|
872
|
-
|
873
|
-
|
1085
|
+
|
1086
|
+
variation_id = ''
|
1087
|
+
variation_id = config.get_variation_id_from_key_by_experiment_id(experiment_id, variation_key) if experiment_id != ''
|
1088
|
+
|
1089
|
+
metadata = {
|
1090
|
+
flag_key: flag_key,
|
1091
|
+
rule_key: rule_key,
|
1092
|
+
rule_type: rule_type,
|
1093
|
+
variation_key: variation_key,
|
1094
|
+
enabled: enabled
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
user_event = UserEventFactory.create_impression_event(config, experiment, variation_id, metadata, user_id, attributes)
|
874
1098
|
@event_processor.process(user_event)
|
875
1099
|
return unless @notification_center.notification_count(NotificationCenter::NOTIFICATION_TYPES[:ACTIVATE]).positive?
|
876
1100
|
|
877
1101
|
@logger.log(Logger::INFO, "Activating user '#{user_id}' in experiment '#{experiment_key}'.")
|
878
|
-
|
1102
|
+
|
1103
|
+
experiment = nil if experiment_id == ''
|
1104
|
+
variation = nil
|
1105
|
+
variation = config.get_variation_from_id_by_experiment_id(experiment_id, variation_id) unless experiment.nil?
|
879
1106
|
log_event = EventFactory.create_log_event(user_event, @logger)
|
880
1107
|
@notification_center.send_notifications(
|
881
1108
|
NotificationCenter::NOTIFICATION_TYPES[:ACTIVATE],
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optimizely-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Optimizely
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -141,6 +141,9 @@ files:
|
|
141
141
|
- lib/optimizely/config_manager/project_config_manager.rb
|
142
142
|
- lib/optimizely/config_manager/static_project_config_manager.rb
|
143
143
|
- lib/optimizely/custom_attribute_condition_evaluator.rb
|
144
|
+
- lib/optimizely/decide/optimizely_decide_option.rb
|
145
|
+
- lib/optimizely/decide/optimizely_decision.rb
|
146
|
+
- lib/optimizely/decide/optimizely_decision_message.rb
|
144
147
|
- lib/optimizely/decision_service.rb
|
145
148
|
- lib/optimizely/error_handler.rb
|
146
149
|
- lib/optimizely/event/batch_event_processor.rb
|
@@ -172,6 +175,7 @@ files:
|
|
172
175
|
- lib/optimizely/notification_center.rb
|
173
176
|
- lib/optimizely/optimizely_config.rb
|
174
177
|
- lib/optimizely/optimizely_factory.rb
|
178
|
+
- lib/optimizely/optimizely_user_context.rb
|
175
179
|
- lib/optimizely/params.rb
|
176
180
|
- lib/optimizely/project_config.rb
|
177
181
|
- lib/optimizely/semantic_version.rb
|
@@ -196,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
200
|
- !ruby/object:Gem::Version
|
197
201
|
version: '0'
|
198
202
|
requirements: []
|
199
|
-
rubygems_version: 3.0.
|
203
|
+
rubygems_version: 3.0.1
|
200
204
|
signing_key:
|
201
205
|
specification_version: 4
|
202
206
|
summary: Ruby SDK for Optimizely's testing framework
|