kameleoon-client-ruby 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b1daddd63c5a75a2eadf683c4055b70a748b9aaff7326c4ec22913eca3b733a
4
- data.tar.gz: 128608fb9a5060581a884ac46f36e2e73cca216f27acf97f2163947bfbc07477
3
+ metadata.gz: 887e6709dff33fa410a8e34a32577d8ad1ffe56fa52cadd24bd1734c68d2e46b
4
+ data.tar.gz: e42d4d944e8c1549eae488f74e7b5c8891bf41f35dcce02133bfc68cee969463
5
5
  SHA512:
6
- metadata.gz: e33eeba8b980325174d203c2d0e5ea11ad99565f8e14f6e9be48e962ec1038b972347c5d34f9171e47bf7999cf8b5cafad128a541da2a82e367a84b02c2aedbc
7
- data.tar.gz: 4135c9bd59d70db3c67cc3d887d02b41fb890b1d8a31dfafd25a5e46946c27cab1c8de7249156e483ad7b224c109146d0b33f79a80e9bc0db6ca54bc094a6c3e
6
+ metadata.gz: 3cf8ee8561091145b530082e2ce86614b41f9c63c70b644518c5a9d3738e659084526003ad298cdf320da0570cc7d55b551b3b80e680877a1c4c0bd984bc1b9f
7
+ data.tar.gz: 4c9e4873467d1f2578be20f8246a47ad3810401251fb9e3dd34d3baad073184c6083fa0a35893c95e308a3482ebb3b42d58e1fd8e82c9400fa554ebbd1e16d63
data/README.md CHANGED
@@ -1,22 +1,7 @@
1
- # Kameleoon RUBY SDK
1
+ # Kameleoon Ruby SDK
2
2
 
3
- This is the repository for the Kameleoon Ruby SDK.
3
+ ## Getting Started
4
4
 
5
- ### How to build and install Kameleoon Gem locally
6
- #### Prerequisite:
7
- * [Install ruby](https://www.ruby-lang.org/en/documentation/installation)
5
+ Our SDK gives you the possibility of running experiments and activating feature flags on your Ruby platform. Integrating our SDK into your applications is easy, and its footprint (in terms of memory and network usage) is low.
8
6
 
9
- #### Build and install the gem:
10
- * Run `./buildAndInstallGem.sh`
11
-
12
- ### How to run tests
13
- #### Prerequisite:
14
- * Build and install Kameleoon Gem locally (infos above).
15
- * Install rake: `gem install rake`
16
-
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`
7
+ You can refer to the [SDK reference](https://developers.kameleoon.com/ruby-sdk.html#reference) to check out all possible features of the SDK. Also make sure you check out our [Getting started tutorial](https://developers.kameleoon.com/ruby-sdk.html#getting-started) which we have prepared to walk you through the installation and implementation.
@@ -2,11 +2,13 @@ require 'kameleoon/targeting/models'
2
2
  require 'kameleoon/request'
3
3
  require 'kameleoon/exceptions'
4
4
  require 'kameleoon/cookie'
5
+ require 'kameleoon/query_graphql'
5
6
  require 'rufus/scheduler'
6
7
  require 'yaml'
7
8
  require 'json'
8
9
  require 'em-synchrony'
9
10
  require 'objspace'
11
+ require 'time'
10
12
 
11
13
  module Kameleoon
12
14
  ##
@@ -83,8 +85,10 @@ module Kameleoon
83
85
  # @raise [Kameleoon::Exception::ExperimentConfigurationNotFound] Raise when experiment configuration is not found
84
86
  # @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
85
87
  # @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
88
+ # @raise [Kameleoon::Exception::VisitorCodeNotValid] If the visitor code is empty or longer than 255 chars
86
89
  #
87
90
  def trigger_experiment(visitor_code, experiment_id, timeout = @default_timeout)
91
+ check_visitor_code(visitor_code)
88
92
  experiment = @experiments.find { |experiment| experiment['id'].to_s == experiment_id.to_s }
89
93
  if experiment.nil?
90
94
  raise Exception::ExperimentConfigurationNotFound.new(experiment_id)
@@ -143,7 +147,10 @@ module Kameleoon
143
147
  # @param [String] visitor_code Visitor code
144
148
  # @param [...Data] data Data to associate with the visitor code
145
149
  #
150
+ # @raise [Kameleoon::Exception::VisitorCodeNotValid] If the visitor code is empty or longer than 255 chars
151
+ #
146
152
  def add_data(visitor_code, *args)
153
+ check_visitor_code(visitor_code)
147
154
  while ObjectSpace.memsize_of(@data) > @data_maximum_size * (2**20) do
148
155
  @data.shift
149
156
  end
@@ -167,7 +174,10 @@ module Kameleoon
167
174
  # @param [Integer] goal_id Id of the goal
168
175
  # @param [Float] revenue Optional - Revenue of the conversion.
169
176
  #
177
+ # @raise [Kameleoon::Exception::VisitorCodeNotValid] If the visitor code is empty or longer than 255 chars
178
+ #
170
179
  def track_conversion(visitor_code, goal_id, revenue = 0.0)
180
+ check_visitor_code(visitor_code)
171
181
  add_data(visitor_code, Conversion.new(goal_id, revenue))
172
182
  flush(visitor_code)
173
183
  end
@@ -181,7 +191,10 @@ module Kameleoon
181
191
  #
182
192
  # @param [String] visitor_code Optional field - Visitor code, without visitor code it flush all of the data
183
193
  #
194
+ # @raise [Kameleoon::Exception::VisitorCodeNotValid] If the visitor code is not null and empty or longer than 255 chars
195
+ #
184
196
  def flush(visitor_code = nil)
197
+ check_visitor_code(visitor_code) unless visitor_code.nil?
185
198
  track_data(visitor_code)
186
199
  end
187
200
 
@@ -203,9 +216,9 @@ module Kameleoon
203
216
  def obtain_variation_associated_data(variation_id)
204
217
  variation = @experiments.map { |experiment| experiment['variations'] }.flatten.select { |variation| variation['id'].to_i == variation_id.to_i }.first
205
218
  if variation.nil?
206
- raise Exception::VariationNotFound.new(variation_id)
219
+ raise Exception::VariationConfigurationNotFound.new(variation_id)
207
220
  else
208
- variation['customJson']
221
+ JSON.parse(variation['customJson'])
209
222
  end
210
223
  end
211
224
 
@@ -221,8 +234,10 @@ module Kameleoon
221
234
  #
222
235
  # @raise [Kameleoon::Exception::FeatureConfigurationNotFound]
223
236
  # @raise [Kameleoon::Exception::NotTargeted]
237
+ # @raise [Kameleoon::Exception::VisitorCodeNotValid] If the visitor code is empty or longer than 255 chars
224
238
  #
225
239
  def activate_feature(visitor_code, feature_key, timeout = @default_timeout)
240
+ check_visitor_code(visitor_code)
226
241
  feature_flag = get_feature_flag(feature_key)
227
242
  id = feature_flag['id']
228
243
  if @blocking
@@ -248,17 +263,21 @@ module Kameleoon
248
263
 
249
264
  else
250
265
  visitor_data = @data.select { |key, value| key.to_s == visitor_code }.values.flatten! || []
251
- if feature_flag['targetingSegment'].nil? || feature_flag['targetingSegment'].check_tree(visitor_data)
266
+ unless feature_flag['targetingSegment'].nil? || feature_flag['targetingSegment'].check_tree(visitor_data)
267
+ raise Exception::NotTargeted.new(visitor_code)
268
+ end
269
+
270
+ if is_feature_flag_scheduled(feature_flag, Time.now.to_i)
252
271
  threshold = obtain_hash_double(visitor_code, {}, id)
253
272
  if threshold <= feature_flag['expositionRate']
254
- track_experiment(visitor_code, id, feature_flag["variationsId"].first)
255
- return true
273
+ track_experiment(visitor_code, id, feature_flag["variations"].first['id'])
274
+ true
256
275
  else
257
276
  track_experiment(visitor_code, id, REFERENCE, true)
258
- return false
277
+ false
259
278
  end
260
279
  else
261
- raise Exception::NotTargeted.new(visitor_code)
280
+ false
262
281
  end
263
282
  end
264
283
  end
@@ -276,19 +295,19 @@ module Kameleoon
276
295
  #
277
296
  def obtain_feature_variable(feature_key, variable_key)
278
297
  feature_flag = get_feature_flag(feature_key)
279
- custom_json = feature_flag["variations"].first['customJson'][variable_key.to_s]
298
+ custom_json = JSON.parse(feature_flag["variations"].first['customJson'])[variable_key.to_s]
280
299
  if custom_json.nil?
281
300
  raise Exception::FeatureVariableNotFound.new("Feature variable not found")
282
301
  end
283
302
  case custom_json['type']
284
303
  when "Boolean"
285
- return !!custom_json['value']
304
+ return custom_json['value'].downcase == "true"
286
305
  when "String"
287
- return custom_json['value'].to_s
288
- when "Number"
289
- return custom_json['value'].to_f
290
- when "Json"
291
306
  return custom_json['value']
307
+ when "Number"
308
+ return custom_json['value'].to_i
309
+ when "JSON"
310
+ return JSON.parse(custom_json['value'])
292
311
  else
293
312
  raise TypeError.new("Unknown type for feature variable")
294
313
  end
@@ -297,6 +316,8 @@ module Kameleoon
297
316
  private
298
317
  API_SSX_URL = "https://api-ssx.kameleoon.com"
299
318
  REFERENCE = 0
319
+ STATUS_ACTIVE = "ACTIVE"
320
+ FEATURE_STATUS_DEACTIVATED = "DEACTIVATED"
300
321
  attr :site_code, :client_id, :client_secret, :access_token, :experiments, :feature_flags, :scheduler, :data,
301
322
  :blocking, :tracking_url, :default_timeout, :interval, :memory_limit, :verbose_mode
302
323
 
@@ -304,11 +325,20 @@ module Kameleoon
304
325
  @scheduler = Rufus::Scheduler.singleton
305
326
  @scheduler.every @interval do
306
327
  log("Scheduled job to fetch configuration is starting.")
307
- fetch_configuration_job
328
+ fetch_configuration_job_graphql
308
329
  end
309
330
  @scheduler.schedule '0s' do
310
331
  log("Start-up, fetching is starting")
311
- fetch_configuration_job
332
+ fetch_configuration_job_graphql
333
+ end
334
+ end
335
+
336
+ def fetch_configuration_job_graphql
337
+ EM.synchrony do
338
+ obtain_access_token
339
+ @experiments = obtain_experiments_graphql(@site_code) || @experiments
340
+ @feature_flags = obtain_feature_flags_graphql(@site_code) || @feature_flags
341
+ EM.stop
312
342
  end
313
343
  end
314
344
 
@@ -387,8 +417,37 @@ module Kameleoon
387
417
  end
388
418
 
389
419
  def complete_experiment(experiment)
390
- unless experiment['variationsId'].nil?
391
- experiment['variations'] = experiment['variationsId'].map { |variationId| obtain_variation(variationId) }
420
+ unless experiment['variations'].nil?
421
+ experiment['variations'] = experiment['variations'].map { |variationId| obtain_variation(variationId) }
422
+ end
423
+ unless experiment['targetingSegmentId'].nil?
424
+ experiment['targetingSegment'] = Kameleoon::Targeting::Segment.new(obtain_segment(experiment['targetingSegmentId']))
425
+ end
426
+ experiment
427
+ end
428
+
429
+ # fetching segment for both types: experiments and feature_flags (campaigns)
430
+ def complete_campaign_graphql(campaign)
431
+ campaign['id'] = campaign['id'].to_i
432
+ campaign['status'] = campaign['status']
433
+ unless campaign['deviations'].nil?
434
+ campaign['deviations'] = Hash[*campaign['deviations'].map { |it| [ it['variationId'] == '0' ? 'origin' : it['variationId'], it['value'] ] }.flatten]
435
+ end
436
+ unless campaign['respoolTime'].nil?
437
+ campaign['respoolTime'] = Hash[*campaign['respoolTime'].map { |it| [ it['variationId'] == '0' ? 'origin' : it['variationId'], it['value'] ] }.flatten]
438
+ end
439
+ unless campaign['variations'].nil?
440
+ campaign['variations'] = campaign['variations'].map { |it| {'id' => it['id'].to_i, 'customJson' => it['customJson']} }
441
+ end
442
+ unless campaign['segment'].nil?
443
+ campaign['targetingSegment'] = Kameleoon::Targeting::Segment.new((campaign['segment']))
444
+ end
445
+ campaign
446
+ end
447
+
448
+ def complete_experiment(experiment)
449
+ unless experiment['variations'].nil?
450
+ experiment['variations'] = experiment['variations'].map { |variationId| obtain_variation(variationId) }
392
451
  end
393
452
  unless experiment['targetingSegmentId'].nil?
394
453
  experiment['targetingSegment'] = Kameleoon::Targeting::Segment.new(obtain_segment(experiment['targetingSegmentId']))
@@ -396,6 +455,15 @@ module Kameleoon
396
455
  experiment
397
456
  end
398
457
 
458
+ def obtain_experiments_graphql(site_code, per_page = -1)
459
+ log "Fetching experiments GraphQL"
460
+ experiments = fetch_all_graphql("v1/graphql?perPage=#{per_page}", Kameleoon::Query.query_experiments(site_code)).map { |it| JSON.parse(it.response)['data']['experiments']['edges'] }.flatten.map do |experiment|
461
+ complete_campaign_graphql(experiment['node'])
462
+ end
463
+ log "Experiment are fetched: " + experiments.inspect
464
+ experiments
465
+ end
466
+
399
467
  def obtain_tests(site_id, per_page = -1)
400
468
  log "Fetching experiments"
401
469
  query_values = { 'perPage' => per_page }
@@ -411,12 +479,21 @@ module Kameleoon
411
479
  experiments
412
480
  end
413
481
 
482
+ def obtain_feature_flags_graphql(site_id, per_page = -1)
483
+ log "Fetching feature flags GraphQL"
484
+ feature_flags = fetch_all_graphql("v1/graphql?perPage=#{per_page}", Kameleoon::Query.query_feature_flags(site_code)).map { |it| JSON.parse(it.response)['data']['featureFlags']['edges'] }.flatten.map do |feature_flag|
485
+ complete_campaign_graphql(feature_flag['node'])
486
+ end
487
+ log "Feature flags are fetched: " + feature_flags.inspect
488
+ feature_flags
489
+ end
490
+
414
491
  def obtain_feature_flags(site_id, per_page = -1)
415
492
  log "Fetching feature flags"
416
493
  query_values = { 'perPage' => per_page }
417
494
  filters = [
418
495
  hash_filter('siteId', 'EQUAL', [site_id]),
419
- hash_filter('status', 'EQUAL', ['ACTIVE'])
496
+ hash_filter('status', 'IN', ['ACTIVE', 'PAUSED'])
420
497
  ]
421
498
  feature_flags = fetch_all('feature-flags', query_values, filters).map { |it| JSON.parse(it.response) }.flatten.map do |ff|
422
499
  complete_experiment(ff)
@@ -425,6 +502,19 @@ module Kameleoon
425
502
  feature_flags
426
503
  end
427
504
 
505
+ def fetch_all_graphql(path, query_graphql = {})
506
+ results = []
507
+ current_page = 1
508
+ loop do
509
+ http = fetch_one_graphql(path, query_graphql)
510
+ break if http == false
511
+ results.push(http)
512
+ break if http.response_header["X-Pagination-Page-Count"].to_i <= current_page
513
+ current_page += 1
514
+ end
515
+ results
516
+ end
517
+
428
518
  def fetch_all(path, query_values = {}, filters = [])
429
519
  results = []
430
520
  current_page = 1
@@ -439,6 +529,15 @@ module Kameleoon
439
529
  results
440
530
  end
441
531
 
532
+ def fetch_one_graphql(path, query_graphql = {})
533
+ request = EM::Synchrony.sync post({ :path => path, :body => query_graphql, :head => hash_headers })
534
+ unless is_successful(request)
535
+ log "Failed to fetch" + request.inspect
536
+ return false
537
+ end
538
+ request
539
+ end
540
+
442
541
  def fetch_one(path, query_values = {}, filters = [])
443
542
  unless filters.empty?
444
543
  query_values['filter'] = filters.to_json
@@ -490,6 +589,20 @@ module Kameleoon
490
589
  feature_flag
491
590
  end
492
591
 
592
+ def is_feature_flag_scheduled(feature_flag, date)
593
+ current_status = feature_flag['status'] == STATUS_ACTIVE
594
+ if feature_flag['featureStatus'] == FEATURE_STATUS_DEACTIVATED || feature_flag['schedules'].empty?
595
+ return current_status
596
+ end
597
+ feature_flag['schedules'].each do |schedule|
598
+ if (schedule['dateStart'].nil? || Time.parse(schedule['dateStart']).to_i < date) &&
599
+ (schedule['dateEnd'].nil? || Time.parse(schedule['dateEnd']).to_i > date)
600
+ return true
601
+ end
602
+ end
603
+ false
604
+ end
605
+
493
606
  def track_experiment(visitor_code, experiment_id, variation_id = nil, none_variation = false)
494
607
  data_not_sent = data_not_sent(visitor_code)
495
608
  options = {
@@ -498,6 +611,7 @@ module Kameleoon
498
611
  :head => { "Content-Type" => "text/plain"}
499
612
  }
500
613
  trial = 0
614
+ success = false
501
615
  log "Start post tracking experiment: " + data_not_sent.inspect
502
616
  Thread.new do
503
617
  EM.synchrony do
@@ -507,12 +621,18 @@ module Kameleoon
507
621
  if is_successful(request)
508
622
  (data_not_sent.values[0] || []).each { |it| it.sent = true }
509
623
  EM.stop
624
+ success = true
625
+ break
510
626
  end
511
627
  trial += 1
512
628
  end
513
629
  EM.stop
514
630
  end
515
- log "Post to experiment tracking is done after " + trial.to_s + " trials"
631
+ if success
632
+ log "Post to experiment tracking is done after " + (trial + 1).to_s + " trials"
633
+ elsif
634
+ log "Post to experiment tracking is failed after " + trial.to_s + " trials"
635
+ end
516
636
  Thread.exit
517
637
  end
518
638
  end
@@ -565,4 +685,4 @@ module Kameleoon
565
685
  end
566
686
  end
567
687
  end
568
- end
688
+ end
@@ -26,10 +26,18 @@ module Kameleoon
26
26
  identifier = visitor_code.to_s
27
27
  identifier += container_id.to_s
28
28
  if !respool_times.nil? && !respool_times.empty?
29
- identifier += respool_times.values.sort.join.to_s
29
+ identifier += respool_times.sort.to_h.values.join.to_s
30
30
  end
31
31
  (Digest::SHA256.hexdigest(identifier.encode('UTF-8')).to_i(16) / (BigDecimal("2") ** BigDecimal("256"))).round(16)
32
32
  end
33
+
34
+ def check_visitor_code(visitor_code)
35
+ if visitor_code.nil?
36
+ check_default_visitor_code('')
37
+ elsif
38
+ check_default_visitor_code(visitor_code)
39
+ end
40
+ end
33
41
 
34
42
  private
35
43
 
@@ -1,4 +1,3 @@
1
-
2
1
  module Kameleoon
3
2
  NONCE_LENGTH = 16
4
3
 
@@ -29,6 +28,17 @@ module Kameleoon
29
28
  def obtain_full_post_text_line
30
29
  raise KameleoonError.new("ToDo: implement this method.")
31
30
  end
31
+
32
+ def encode(url)
33
+ encoded_url = CGI.escape(url)
34
+ encoded_url.gsub! "%27", "'"
35
+ encoded_url.gsub! "%21", "!"
36
+ encoded_url.gsub! "+", "%20"
37
+ encoded_url.gsub! "%2A", "*"
38
+ encoded_url.gsub! "%28", "("
39
+ encoded_url.gsub! "%29", ")"
40
+ encoded_url
41
+ end
32
42
  end
33
43
 
34
44
  class CustomData < Data
@@ -63,7 +73,7 @@ module Kameleoon
63
73
  def obtain_full_post_text_line
64
74
  to_encode = "[[\"" + @value.to_s.gsub("\"", "\\\"") + "\",1]]"
65
75
  nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
66
- "eventType=customData&index=" + @id.to_s + "&valueToCount=" + URI.encode_www_form_component(to_encode) + "&overwrite=true&nonce=" + nonce
76
+ "eventType=customData&index=" + @id.to_s + "&valueToCount=" + encode(to_encode) + "&overwrite=true&nonce=" + nonce
67
77
  end
68
78
  end
69
79
 
@@ -101,9 +111,9 @@ module Kameleoon
101
111
  nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
102
112
  referrer_text = ""
103
113
  unless @referrer.nil?
104
- referrer_text = "&referrers=[" + @referrer + "]"
114
+ referrer_text = "&referrers=[" + @referrer.to_s + "]"
105
115
  end
106
- "eventType=page&href=" + @url + "&title=" + @title + "&keyPages=[]" + referrer_text + "&nonce=" + nonce
116
+ "eventType=page&href=" + encode(@url) + "&title=" + @title + "&keyPages=[]" + referrer_text + "&nonce=" + nonce
107
117
  end
108
118
  end
109
119
 
@@ -10,7 +10,7 @@ module Kameleoon
10
10
  super(value.to_s + " not found.")
11
11
  end
12
12
  end
13
- class VariationNotFound < NotFound
13
+ class VariationConfigurationNotFound < NotFound
14
14
  def initialize(id = "")
15
15
  super("Variation " + id.to_s)
16
16
  end
@@ -0,0 +1,66 @@
1
+ module Kameleoon
2
+ module Query
3
+
4
+ def self.query_experiments(site_code)
5
+ '{
6
+ "operationName": "getExperiments",
7
+ "query": "query getExperiments($first: Int, $after: String, $filter: FilteringExpression, $sort: [SortingParameter!]) { experiments(first: $first, after: $after, filter: $filter, sort: $sort) { edges { node { id name type site { id code } status variations { id customJson } deviations { variationId value } respoolTime {variationId value } segment { id name conditionsData { firstLevelOrOperators firstLevel { orOperators conditions { targetingType isInclude ... on CustomDataTargetingCondition { customDataIndex value valueMatchType } } } } } __typename } __typename } pageInfo { endCursor hasNextPage __typename } totalCount __typename } }",
8
+ "variables": {
9
+ "filter": {
10
+ "and": [{
11
+ "condition": {
12
+ "field": "status",
13
+ "operator": "IN",
14
+ "parameters": ["ACTIVE", "DEVIATED", "USED_AS_PERSONALIZATION"]
15
+ }
16
+ }, {
17
+ "condition": {
18
+ "field": "type",
19
+ "operator": "IN",
20
+ "parameters": ["SERVER_SIDE", "HYBRID"]
21
+ }
22
+ }, {
23
+ "condition": {
24
+ "field": "siteCode",
25
+ "operator": "IN",
26
+ "parameters": ["' + site_code + '"]
27
+ }
28
+ }]
29
+ },
30
+ "sort": [{
31
+ "field": "id",
32
+ "direction": "ASC"
33
+ }]
34
+ }
35
+ }'
36
+ end
37
+
38
+ def self.query_feature_flags(site_code)
39
+ '{
40
+ "operationName": "getFeatureFlags",
41
+ "query": "query getFeatureFlags($first: Int, $after: String, $filter: FilteringExpression, $sort: [SortingParameter!]) { featureFlags(first: $first, after: $after, filter: $filter, sort: $sort) { edges { node { id name site { id code } bypassDeviation status variations { id customJson } respoolTime { variationId value } expositionRate identificationKey featureFlagSdkLanguageType featureStatus schedules { dateStart dateEnd } segment { id name conditionsData { firstLevelOrOperators firstLevel { orOperators conditions { targetingType isInclude ... on CustomDataTargetingCondition { customDataIndex value valueMatchType } } } } } __typename } __typename } pageInfo { endCursor hasNextPage __typename } totalCount __typename } }",
42
+ "variables": {
43
+ "filter": {
44
+ "and": [{
45
+ "condition": {
46
+ "field": "featureStatus",
47
+ "operator": "IN",
48
+ "parameters": ["ACTIVATED", "SCHEDULED", "DEACTIVATED"]
49
+ }
50
+ }, {
51
+ "condition": {
52
+ "field": "siteCode",
53
+ "operator": "IN",
54
+ "parameters": ["' + site_code + '"]
55
+ }
56
+ }]
57
+ },
58
+ "sort": [{
59
+ "field": "id",
60
+ "direction": "ASC"
61
+ }]
62
+ }
63
+ }'
64
+ end
65
+ end
66
+ end
@@ -1,4 +1,3 @@
1
- require 'kameleoon/targeting/models'
2
1
  require 'kameleoon/targeting/conditions/custom_datum'
3
2
 
4
3
  module Kameleoon
@@ -1,6 +1,5 @@
1
1
  require 'kameleoon/targeting/condition'
2
2
  require 'kameleoon/exceptions'
3
- require 'kameleoon/targeting/models'
4
3
 
5
4
  module Kameleoon
6
5
  #@api private
@@ -20,17 +19,17 @@ module Kameleoon
20
19
  end
21
20
  @operator = json_condition['valueMatchType']
22
21
 
23
- if json_condition['value'].nil?
24
- raise Exception::NotFoundError.new('value')
25
- end
22
+ # if json_condition['value'].nil?
23
+ # raise Exception::NotFoundError.new('value')
24
+ # end
26
25
  @value = json_condition['value']
27
26
 
28
27
  @type = ConditionType::CUSTOM_DATUM
29
28
 
30
- if json_condition['include'].nil?
31
- raise Exception::NotFoundError.new('include')
29
+ if json_condition['include'].nil? && json_condition['isInclude'].nil?
30
+ raise Exception::NotFoundError.new('include / isInclude missed')
32
31
  end
33
- @include = json_condition['include']
32
+ @include = json_condition['include'] || json_condition['isInclude']
34
33
  end
35
34
 
36
35
  def check(datas)
@@ -65,11 +64,11 @@ module Kameleoon
65
64
  is_targeted = true
66
65
  end
67
66
  when Operator::IS_TRUE.to_s
68
- if custom_data.value == true
67
+ if custom_data.value == 'true'
69
68
  is_targeted = true
70
69
  end
71
70
  when Operator::IS_FALSE.to_s
72
- if custom_data.value == false
71
+ if custom_data.value == 'false'
73
72
  is_targeted = true
74
73
  end
75
74
  else
@@ -23,7 +23,7 @@ module Kameleoon
23
23
  if hash["id"].nil?
24
24
  raise Kameleoon::Exception::NotFound.new("id")
25
25
  end
26
- @id = hash["id"]
26
+ @id = hash["id"].to_i
27
27
  if hash["conditionsData"].nil?
28
28
  raise Kameleoon::Exception::NotFound.new(hash["conditionsData"])
29
29
  end
@@ -1,5 +1,4 @@
1
1
  require 'kameleoon/targeting/condition_factory'
2
- require 'kameleoon/targeting/models'
3
2
 
4
3
  module Kameleoon
5
4
  #@api private
@@ -1,3 +1,3 @@
1
1
  module Kameleoon
2
- VERSION = '1.0.8'
2
+ VERSION = '1.0.9'
3
3
  end
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.8
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
- - Kameleoon - Guillaume Grandjean
7
+ - Kameleoon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-27 00:00:00.000000000 Z
11
+ date: 2021-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '3.7'
55
55
  description: Kameleoon Client Ruby Software Development Kit
56
56
  email:
57
- - ggrandjean@kameleoon.com
57
+ - sdk@kameleoon.com
58
58
  executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
@@ -66,6 +66,7 @@ files:
66
66
  - lib/kameleoon/data.rb
67
67
  - lib/kameleoon/exceptions.rb
68
68
  - lib/kameleoon/factory.rb
69
+ - lib/kameleoon/query_graphql.rb
69
70
  - lib/kameleoon/request.rb
70
71
  - lib/kameleoon/targeting/condition.rb
71
72
  - lib/kameleoon/targeting/condition_factory.rb