kameleoon-client-ruby 1.0.0 → 1.0.1
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/README.md +7 -3
- data/lib/kameleoon.rb +1 -1
- data/lib/kameleoon/client.rb +39 -27
- data/lib/kameleoon/exceptions.rb +7 -2
- data/lib/kameleoon/factory.rb +2 -2
- data/lib/kameleoon/request.rb +11 -1
- data/lib/kameleoon/version.rb +3 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1acddc80101273c13cdf39b6cf2fb497716e947981dbffcf4d31540ea1f62edc
|
4
|
+
data.tar.gz: c00f33ed4eb494f7b1f2b4009005e84492ccad9cc366ac8fd34888c6aa63e2eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b4a67c7e0f8315aaeb2e46c15c2961840099a40a874d56c821bfc5407aa4f506ea732cf90cad13abb406e1c2f6d98bea62fb07a9b7bf427798ad27a15ef11e3
|
7
|
+
data.tar.gz: a62a96d1a772835c9e4db7ad8c968c302339dae2b9937204c37bbd2d8f22f23d6c76dae15b8f8577a0e692e1a181d27177635e64fba0f1b090290c870c0f9034
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ This is the repository for the Kameleoon Ruby SDK.
|
|
6
6
|
#### Prerequisite:
|
7
7
|
* [Install ruby](https://www.ruby-lang.org/en/documentation/installation)
|
8
8
|
|
9
|
-
#### Build and install:
|
9
|
+
#### Build and install the gem:
|
10
10
|
* Run `./buildAndInstallGem.sh`
|
11
11
|
|
12
12
|
### How to run tests
|
@@ -14,5 +14,9 @@ This is the repository for the Kameleoon Ruby SDK.
|
|
14
14
|
* Build and install Kameleoon Gem locally (infos above).
|
15
15
|
* Install rake: `gem install rake`
|
16
16
|
|
17
|
-
####
|
18
|
-
|
17
|
+
#### Run Tests:
|
18
|
+
##### Unit
|
19
|
+
* Run `./test.sh -u`
|
20
|
+
##### Integration
|
21
|
+
Make sure you kill manually the server test app after the tests are done.
|
22
|
+
* Run `./test.sh -i`
|
data/lib/kameleoon.rb
CHANGED
data/lib/kameleoon/client.rb
CHANGED
@@ -19,16 +19,17 @@ module Kameleoon
|
|
19
19
|
|
20
20
|
##
|
21
21
|
# You should create Client with the Client Factory only.
|
22
|
+
#
|
22
23
|
def initialize(site_code, path_config_file, blocking, interval, default_timeout, client_id = nil, client_secret = nil)
|
23
24
|
config = YAML.load_file(path_config_file)
|
24
25
|
@site_code = site_code
|
25
26
|
@blocking = blocking
|
26
|
-
@default_timeout = config['default_timeout'] || default_timeout
|
27
|
-
@interval = config['actions_configuration_refresh_interval'] || interval
|
27
|
+
@default_timeout = config['default_timeout'] || default_timeout # in ms
|
28
|
+
@interval = config['actions_configuration_refresh_interval'].to_s + 'm' || interval
|
28
29
|
@tracking_url = config['tracking_url'] || "https://api-ssx.kameleoon.com"
|
29
30
|
@client_id = client_id || config['client_id']
|
30
31
|
@client_secret = client_secret || config['client_secret']
|
31
|
-
@data_maximum_size = config['visitor_data_maximum_size'] || 500
|
32
|
+
@data_maximum_size = config['visitor_data_maximum_size'] || 500 # mb
|
32
33
|
@experiments = []
|
33
34
|
@feature_flags = []
|
34
35
|
@data = {}
|
@@ -37,7 +38,6 @@ module Kameleoon
|
|
37
38
|
##
|
38
39
|
# Obtain a visitor code.
|
39
40
|
#
|
40
|
-
#
|
41
41
|
# This method should be called to obtain the Kameleoon visitor_code for the current visitor.
|
42
42
|
# This is especially important when using Kameleoon in a mixed front-end and back-end environment,
|
43
43
|
# where user identification consistency must be guaranteed.
|
@@ -51,10 +51,9 @@ module Kameleoon
|
|
51
51
|
# In any case, the server-side (via HTTP header) kameleoonVisitorCode cookie is set with the value. Then this
|
52
52
|
# identifier value is finally returned by the method.
|
53
53
|
#
|
54
|
-
#
|
55
54
|
# @param [Hash] cookies Cookies of the request.
|
56
55
|
# @param [String] top_level_domain Top level domain of your website, settled while writing cookie.
|
57
|
-
# @param [String]
|
56
|
+
# @param [String] default_visitor_code - Optional - Define your default visitor_code (maximum length 100 chars).
|
58
57
|
#
|
59
58
|
# @return [String] visitor code
|
60
59
|
#
|
@@ -68,6 +67,7 @@ module Kameleoon
|
|
68
67
|
|
69
68
|
##
|
70
69
|
# Trigger an experiment.
|
70
|
+
#
|
71
71
|
# If such a visitor_code has never been associated with any variation, the SDK returns a randomly selected variation.
|
72
72
|
# If a user with a given visitor_code is already registered with a variation, it will detect the previously
|
73
73
|
# registered variation and return the variation_id.
|
@@ -77,20 +77,21 @@ module Kameleoon
|
|
77
77
|
# @param [String] visitor_code Visitor code
|
78
78
|
# @param [Integer] experiment_id Id of the experiment you want to trigger.
|
79
79
|
#
|
80
|
-
# @return [Integer]
|
80
|
+
# @return [Integer] Id of the variation
|
81
81
|
#
|
82
|
-
# @raise [Kameleoon::Exception::
|
82
|
+
# @raise [Kameleoon::Exception::ExperimentConfigurationNotFound] Raise when experiment configuration is not found
|
83
83
|
# @raise [Kameleoon::Exception::NotActivated] The visitor triggered the experiment, but did not activate it. Usually, this happens because the user has been associated with excluded traffic
|
84
84
|
# @raise [Kameleoon::Exception::NotTargeted] The visitor is not targeted by the experiment, as the associated targeting segment conditions were not fulfilled. He should see the reference variation
|
85
|
+
#
|
85
86
|
def trigger_experiment(visitor_code, experiment_id, timeout = @default_timeout)
|
86
87
|
experiment = @experiments.find { |experiment| experiment['id'].to_s == experiment_id.to_s }
|
87
88
|
if experiment.nil?
|
88
|
-
raise Exception::
|
89
|
+
raise Exception::ExperimentConfigurationNotFound.new(experiment_id)
|
89
90
|
end
|
90
91
|
if @blocking
|
91
92
|
variation_id = nil
|
92
93
|
EM.synchrony do
|
93
|
-
connexion_options = { :connect_timeout => timeout }
|
94
|
+
connexion_options = { :connect_timeout => (timeout.to_f / 1000.0) }
|
94
95
|
body = @data.values.flatten.select { |data| !data.sent }.map { |data| data.obtain_full_post_text_line }
|
95
96
|
.join("\n") || ""
|
96
97
|
path = get_experiment_register_url(visitor_code, experiment_id)
|
@@ -99,7 +100,7 @@ module Kameleoon
|
|
99
100
|
if is_successful(request)
|
100
101
|
variation_id = request.response
|
101
102
|
else
|
102
|
-
raise Exception::
|
103
|
+
raise Exception::ExperimentConfigurationNotFound.new(experiment_id) if variation_id.nil?
|
103
104
|
end
|
104
105
|
EM.stop
|
105
106
|
end
|
@@ -128,7 +129,9 @@ module Kameleoon
|
|
128
129
|
end
|
129
130
|
|
130
131
|
##
|
131
|
-
# Associate various data to a visitor.
|
132
|
+
# Associate various data to a visitor.
|
133
|
+
#
|
134
|
+
# Note that this method doesn't return any value and doesn't interact with the
|
132
135
|
# Kameleoon back-end servers by itself. Instead, the declared data is saved for future sending via the flush method.
|
133
136
|
# This reduces the number of server calls made, as data is usually grouped into a single server call triggered by
|
134
137
|
# the execution of the flush method.
|
@@ -151,13 +154,14 @@ module Kameleoon
|
|
151
154
|
|
152
155
|
##
|
153
156
|
# Track conversions on a particular goal
|
157
|
+
#
|
154
158
|
# This method requires visitor_code and goal_id to track conversion on this particular goal.
|
155
159
|
# In addition, this method also accepts revenue as a third optional argument to track revenue. The visitor_code usually is identical to the one that was used when triggering the experiment.
|
156
160
|
# The track_conversion method doesn't return any value. This method is non-blocking as the server call is made asynchronously.
|
157
161
|
#
|
158
162
|
# @param [String] visitor_code Visitor code
|
159
163
|
# @param [Integer] goal_id Id of the goal
|
160
|
-
# @param [Float] revenue Revenue of the conversion.
|
164
|
+
# @param [Float] revenue Optional - Revenue of the conversion.
|
161
165
|
#
|
162
166
|
def track_conversion(visitor_code, goal_id, revenue = 0.0)
|
163
167
|
add_data(visitor_code, Conversion.new(goal_id, revenue))
|
@@ -166,6 +170,7 @@ module Kameleoon
|
|
166
170
|
|
167
171
|
##
|
168
172
|
# Flush the associated data.
|
173
|
+
#
|
169
174
|
# The data added with the method add_data, is not directly sent to the kameleoon servers.
|
170
175
|
# It's stored and accumulated until it is sent automatically by the trigger_experiment or track_conversion methods.
|
171
176
|
# With this method you can manually send it.
|
@@ -178,6 +183,7 @@ module Kameleoon
|
|
178
183
|
|
179
184
|
##
|
180
185
|
# Obtain variation associated data.
|
186
|
+
#
|
181
187
|
# To retrieve JSON data associated with a variation, call the obtain_variation_associated_data method of our SDK.
|
182
188
|
# The JSON data usually represents some metadata of the variation, and can be configured on our web application
|
183
189
|
# interface or via our Automation API.
|
@@ -186,20 +192,21 @@ module Kameleoon
|
|
186
192
|
#
|
187
193
|
# @param [Integer] variation_id
|
188
194
|
#
|
189
|
-
# @return [
|
195
|
+
# @return [Hash] Hash object of the json object.
|
190
196
|
#
|
191
197
|
# @raise [Kameleoon::Exception::VariationNotFound] Raise exception if the variation is not found.
|
198
|
+
#
|
192
199
|
def obtain_variation_associated_data(variation_id)
|
193
200
|
variation = @experiments.map { |experiment| experiment['variations'] }.flatten.select { |variation| variation['id'].to_i == variation_id.to_i }.first
|
194
201
|
if variation.nil?
|
195
202
|
raise Exception::VariationNotFound.new(variation_id)
|
196
203
|
else
|
197
|
-
variation['customJson']
|
204
|
+
variation['customJson']
|
198
205
|
end
|
199
206
|
end
|
200
207
|
|
201
208
|
#
|
202
|
-
#
|
209
|
+
# Activate a feature toggle.
|
203
210
|
#
|
204
211
|
# This method takes a visitor_code and feature_key (or feature_id) as mandatory arguments to check if the specified feature will be active for a given user.
|
205
212
|
# If such a user has never been associated with this feature flag, the SDK returns a boolean value randomly (true if the user should have this feature or false if not). If a user with a given visitorCode is already registered with this feature flag, it will detect the previous featureFlag value.
|
@@ -208,15 +215,16 @@ module Kameleoon
|
|
208
215
|
# @param [String] visitor_code
|
209
216
|
# @param [String | Integer] feature_key
|
210
217
|
#
|
211
|
-
# @raise [Kameleoon::Exception::
|
218
|
+
# @raise [Kameleoon::Exception::FeatureConfigurationNotFound]
|
212
219
|
# @raise [Kameleoon::Exception::NotTargeted]
|
220
|
+
#
|
213
221
|
def activate_feature(visitor_code, feature_key, timeout = @default_timeout)
|
214
222
|
feature_flag = get_feature_flag(feature_key)
|
215
223
|
id = feature_flag['id']
|
216
224
|
if @blocking
|
217
225
|
result = nil
|
218
226
|
EM.synchrony do
|
219
|
-
connexion_options = { :connect_timeout => timeout }
|
227
|
+
connexion_options = { :connect_timeout => (timeout.to_f / 1000.0) }
|
220
228
|
request_options = {
|
221
229
|
:path => get_experiment_register_url(visitor_code, id),
|
222
230
|
:body => (select_data_to_sent(visitor_code).values.map { |data| data.obtain_full_post_text_line }.join("\n") || "").encode("UTF-8")
|
@@ -227,7 +235,7 @@ module Kameleoon
|
|
227
235
|
end
|
228
236
|
EM.stop
|
229
237
|
end
|
230
|
-
raise Exception::
|
238
|
+
raise Exception::FeatureConfigurationNotFound.new(id) if result.nil?
|
231
239
|
result.to_s != "null"
|
232
240
|
|
233
241
|
else
|
@@ -248,17 +256,21 @@ module Kameleoon
|
|
248
256
|
end
|
249
257
|
|
250
258
|
##
|
251
|
-
#
|
259
|
+
# Retrieve a feature variable.
|
260
|
+
#
|
261
|
+
# A feature variable can be changed easily via our web application.
|
252
262
|
#
|
253
263
|
# @param [String | Integer] feature_key
|
254
264
|
# @param [String ] variable_key
|
255
265
|
#
|
256
|
-
# @raise [Kameleoon::Exception::
|
266
|
+
# @raise [Kameleoon::Exception::FeatureConfigurationNotFound]
|
267
|
+
# @raise [Kameleoon::Exception::FeatureVariableNotFound]
|
268
|
+
#
|
257
269
|
def obtain_feature_variable(feature_key, variable_key)
|
258
270
|
feature_flag = get_feature_flag(feature_key)
|
259
271
|
custom_json = feature_flag["variations"].first['customJson'][variable_key.to_s]
|
260
272
|
if custom_json.nil?
|
261
|
-
raise Exception::
|
273
|
+
raise Exception::FeatureVariableNotFound.new("Feature variable not found")
|
262
274
|
end
|
263
275
|
case custom_json['type']
|
264
276
|
when "Boolean"
|
@@ -268,9 +280,9 @@ module Kameleoon
|
|
268
280
|
when "Number"
|
269
281
|
return custom_json['value'].to_f
|
270
282
|
when "Json"
|
271
|
-
return custom_json['value']
|
283
|
+
return custom_json['value']
|
272
284
|
else
|
273
|
-
raise
|
285
|
+
raise TypeError.new("Unknown type for feature variable")
|
274
286
|
end
|
275
287
|
end
|
276
288
|
|
@@ -300,8 +312,8 @@ module Kameleoon
|
|
300
312
|
@feature_flags ||= []
|
301
313
|
else
|
302
314
|
site_id = site.first['id']
|
303
|
-
@experiments = obtain_tests(site_id)
|
304
|
-
@feature_flags = obtain_feature_flags(site_id)
|
315
|
+
@experiments = obtain_tests(site_id) || @experiments
|
316
|
+
@feature_flags = obtain_feature_flags(site_id) || @feature_flags
|
305
317
|
end
|
306
318
|
EM.stop
|
307
319
|
end
|
@@ -446,7 +458,7 @@ module Kameleoon
|
|
446
458
|
raise TypeError.new("Feature key should be a String or an Integer.")
|
447
459
|
end
|
448
460
|
if feature_flag.nil?
|
449
|
-
raise Exception::
|
461
|
+
raise Exception::FeatureConfigurationNotFound.new(feature_key)
|
450
462
|
end
|
451
463
|
feature_flag
|
452
464
|
end
|
data/lib/kameleoon/exceptions.rb
CHANGED
@@ -15,16 +15,21 @@ module Kameleoon
|
|
15
15
|
super("Variation " + id.to_s)
|
16
16
|
end
|
17
17
|
end
|
18
|
-
class
|
18
|
+
class ExperimentConfigurationNotFound < NotFound
|
19
19
|
def initialize(id = "")
|
20
20
|
super("Experiment " + id.to_s)
|
21
21
|
end
|
22
22
|
end
|
23
|
-
class
|
23
|
+
class FeatureConfigurationNotFound < NotFound
|
24
24
|
def initialize(id = "")
|
25
25
|
super("Feature flag " + id.to_s)
|
26
26
|
end
|
27
27
|
end
|
28
|
+
class FeatureVariableNotFound < NotFound
|
29
|
+
def initialize(key = "")
|
30
|
+
super("Feature variable " + key.to_s)
|
31
|
+
end
|
32
|
+
end
|
28
33
|
class CredentialsNotFound < NotFound
|
29
34
|
def initialize
|
30
35
|
super("Credentials")
|
data/lib/kameleoon/factory.rb
CHANGED
@@ -2,9 +2,9 @@ require 'kameleoon/client'
|
|
2
2
|
|
3
3
|
module Kameleoon
|
4
4
|
module ClientFactory
|
5
|
-
CONFIGURATION_UPDATE_INTERVAL=
|
5
|
+
CONFIGURATION_UPDATE_INTERVAL = '60m'
|
6
6
|
CONFIG_PATH = "/etc/kameleoon/client-ruby.yaml"
|
7
|
-
DEFAULT_TIMEOUT =
|
7
|
+
DEFAULT_TIMEOUT = 2000 #milli-seconds
|
8
8
|
|
9
9
|
##
|
10
10
|
# Create a kameleoon client object, each call create a new client.
|
data/lib/kameleoon/request.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "em-synchrony/em-http"
|
2
|
+
require "kameleoon/version"
|
2
3
|
|
3
4
|
module Kameleoon
|
4
5
|
# @api private
|
@@ -22,7 +23,8 @@ module Kameleoon
|
|
22
23
|
private
|
23
24
|
|
24
25
|
def request(method, request_options, url, connexion_options)
|
25
|
-
|
26
|
+
#connexion_options[:tls] = {verify_peer: true}
|
27
|
+
add_user_agent(request_options)
|
26
28
|
case method
|
27
29
|
when Method::POST then
|
28
30
|
return EventMachine::HttpRequest.new(url, connexion_options).apost request_options
|
@@ -37,6 +39,14 @@ module Kameleoon
|
|
37
39
|
def is_successful(request)
|
38
40
|
!request.nil? && request != false && /20\d/.match(request.response_header.status.to_s)
|
39
41
|
end
|
42
|
+
|
43
|
+
def add_user_agent(request_options)
|
44
|
+
if request_options[:head].nil?
|
45
|
+
request_options[:head] = {'User-Agent' => 'kameleoon-client-ruby/' + Kameleoon::VERSION}
|
46
|
+
else
|
47
|
+
request_options[:head].store('User-Agent', 'kameleoon-client-ruby/' + Kameleoon::VERSION)
|
48
|
+
end
|
49
|
+
end
|
40
50
|
end
|
41
51
|
end
|
42
52
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kameleoon-client-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kameleoon - Guillaume Grandjean
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-04-
|
11
|
+
date: 2021-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- lib/kameleoon/targeting/models.rb
|
74
74
|
- lib/kameleoon/targeting/tree_builder.rb
|
75
75
|
- lib/kameleoon/utils.rb
|
76
|
+
- lib/kameleoon/version.rb
|
76
77
|
homepage: https://developers.kameleoon.com/ruby-sdk.html
|
77
78
|
licenses:
|
78
79
|
- GPL-3.0
|