kameleoon-client-ruby 2.1.0 → 2.1.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kameleoon/client.rb +79 -133
  3. data/lib/kameleoon/configuration/rule.rb +1 -1
  4. data/lib/kameleoon/data/browser.rb +33 -0
  5. data/lib/kameleoon/data/conversion.rb +26 -0
  6. data/lib/kameleoon/data/custom_data.rb +53 -0
  7. data/lib/kameleoon/data/data.rb +35 -0
  8. data/lib/kameleoon/data/device.rb +26 -0
  9. data/lib/kameleoon/data/page_view.rb +31 -0
  10. data/lib/kameleoon/data/user_agent.rb +14 -0
  11. data/lib/kameleoon/network/activity_event.rb +31 -0
  12. data/lib/kameleoon/network/experiment_event.rb +35 -0
  13. data/lib/kameleoon/network/uri_helper.rb +36 -0
  14. data/lib/kameleoon/network/url_provider.rb +71 -0
  15. data/lib/kameleoon/request.rb +5 -19
  16. data/lib/kameleoon/targeting/condition.rb +40 -11
  17. data/lib/kameleoon/targeting/condition_factory.rb +35 -12
  18. data/lib/kameleoon/targeting/conditions/browser_condition.rb +71 -0
  19. data/lib/kameleoon/targeting/conditions/conversion_condition.rb +21 -0
  20. data/lib/kameleoon/targeting/conditions/custom_datum.rb +60 -65
  21. data/lib/kameleoon/targeting/conditions/device_condition.rb +21 -0
  22. data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -12
  23. data/lib/kameleoon/targeting/conditions/page_title_condition.rb +21 -0
  24. data/lib/kameleoon/targeting/conditions/page_url_condition.rb +21 -0
  25. data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +65 -0
  26. data/lib/kameleoon/targeting/conditions/string_value_condition.rb +40 -0
  27. data/lib/kameleoon/targeting/conditions/target_experiment.rb +4 -8
  28. data/lib/kameleoon/targeting/conditions/unknown_condition.rb +15 -0
  29. data/lib/kameleoon/targeting/conditions/visitor_code_condition.rb +16 -0
  30. data/lib/kameleoon/targeting/models.rb +0 -24
  31. data/lib/kameleoon/utils.rb +1 -1
  32. data/lib/kameleoon/version.rb +28 -1
  33. metadata +22 -3
  34. data/lib/kameleoon/data.rb +0 -175
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/data/data'
4
+ require 'kameleoon/version'
5
+
6
+ module Kameleoon
7
+ # @api private
8
+ module Targeting
9
+ # Helper class for containing sdk information
10
+ class SdkInfo
11
+ attr_reader :language, :version
12
+
13
+ def initialize(language, version)
14
+ @language = language
15
+ @version = version
16
+ end
17
+ end
18
+
19
+ # SdkLanguageCondition is a condition for checking targeting sdk type and version
20
+ class SdkLanguageCondition < Condition
21
+ def initialize(json_condition)
22
+ super(json_condition)
23
+ @sdk_language = json_condition['sdkLanguage']
24
+ @version = json_condition['version']
25
+ @operator = json_condition['versionMatchType']
26
+ end
27
+
28
+ def check(data)
29
+ data.is_a?(SdkInfo) && check_targeting(data)
30
+ end
31
+
32
+ private
33
+
34
+ def check_targeting(sdk_info)
35
+ return false if @sdk_language != sdk_info.language
36
+
37
+ return true if @version.nil?
38
+
39
+ version_components_condition = SdkVersion.get_version_components(@version)
40
+ version_components_sdk_info = SdkVersion.get_version_components(sdk_info.version)
41
+
42
+ return false if version_components_condition.nil? || version_components_sdk_info.nil?
43
+
44
+ major_condition, minor_condition, patch_condition = version_components_condition
45
+ major_sdk, minor_sdk, patch_sdk = version_components_sdk_info
46
+
47
+ case @operator
48
+ when Operator::EQUAL
49
+ major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk == patch_condition
50
+ when Operator::GREATER
51
+ major_sdk > major_condition ||
52
+ (major_sdk == major_condition && minor_sdk > minor_condition) ||
53
+ (major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk > patch_condition)
54
+ when Operator::LOWER
55
+ major_sdk < major_condition ||
56
+ (major_sdk == major_condition && minor_sdk < minor_condition) ||
57
+ (major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk < patch_condition)
58
+ else
59
+ puts "Unexpected comparing operation for SdkLanguage condition: #{@operator}"
60
+ false
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/targeting/condition'
4
+
5
+ module Kameleoon
6
+ # @api private
7
+ module Targeting
8
+ # StringValueCondition is a base class for all conditions where string comparison happens
9
+ class StringValueCondition < Condition
10
+ def initialize(json_condition, value)
11
+ super(json_condition)
12
+ @condition_value = value
13
+ @operator = json_condition['matchType']
14
+ end
15
+
16
+ def check(data)
17
+ data.is_a?(String) && check_targeting(data)
18
+ end
19
+
20
+ protected
21
+
22
+ def check_targeting(value)
23
+ return false if value.nil?
24
+
25
+ case @operator
26
+ when Operator::EXACT
27
+ value == @condition_value
28
+ when Operator::CONTAINS
29
+ value.include?(@condition_value)
30
+ when Operator::REGULAR_EXPRESSION
31
+ pattern = Regexp.new(@condition_value)
32
+ pattern.match?(value)
33
+ else
34
+ puts "Unexpected comparing operation for #{@type} condition: #{@operator}"
35
+ false
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -13,16 +13,12 @@ module Kameleoon
13
13
  def initialize(json_condition)
14
14
  super(json_condition)
15
15
 
16
- if json_condition['experiment'].nil?
17
- raise Exception::NotFound.new('experiment'), 'experiment missed'
18
- end
19
-
20
- @experiment = json_condition['experiment']
21
-
16
+ raise Exception::NotFound.new('experiment'), 'experiment missed' if json_condition['experiment'].nil?
22
17
  if json_condition['variationMatchType'].nil?
23
18
  raise Exception::NotFound.new('variationMatchType'), 'variationMatchType missed'
24
19
  end
25
20
 
21
+ @experiment = json_condition['experiment']
26
22
  @operator = json_condition['variationMatchType']
27
23
  @variation = json_condition['variation']
28
24
  end
@@ -32,9 +28,9 @@ module Kameleoon
32
28
  variation_storage_exist = !variation_storage.nil? && !variation_storage.empty?
33
29
  saved_variation = variation_storage[@experiment] unless variation_storage.nil?
34
30
  case @operator
35
- when Operator::EXACT.to_s
31
+ when Operator::EXACT
36
32
  is_targeted = variation_storage_exist && saved_variation == @variation
37
- when Operator::ANY.to_s
33
+ when Operator::ANY
38
34
  is_targeted = variation_storage_exist
39
35
  end
40
36
  is_targeted
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/targeting/condition'
4
+
5
+ module Kameleoon
6
+ # @api private
7
+ module Targeting
8
+ # UnknownCondition represents not defined condition, always returns that visitor is targeted (true)
9
+ class UnknownCondition < Condition
10
+ def check(_data)
11
+ true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/data/data'
4
+ require_relative 'string_value_condition'
5
+
6
+ module Kameleoon
7
+ # @api private
8
+ module Targeting
9
+ # VisitorCodeCondition is a condition for checking of targeting by visitor code
10
+ class VisitorCodeCondition < StringValueCondition
11
+ def initialize(json_condition)
12
+ super(json_condition, json_condition['visitorCode'])
13
+ end
14
+ end
15
+ end
16
+ end
@@ -133,29 +133,5 @@ module Kameleoon
133
133
  Marshal.load(Marshal.dump(is_targeted)) # Deep copy
134
134
  end
135
135
  end
136
-
137
- module DataType
138
- CUSTOM = 'CUSTOM'
139
- end
140
-
141
- module ConditionType
142
- CUSTOM_DATUM = 'CUSTOM_DATUM'
143
- TARGET_EXPERIMENT = 'TARGET_EXPERIMENT'
144
- EXCLUSIVE_EXPERIMENT = 'EXCLUSIVE_EXPERIMENT'
145
- end
146
-
147
- module Operator
148
- UNDEFINED = 'UNDEFINED'
149
- CONTAINS = 'CONTAINS'
150
- EXACT = 'EXACT'
151
- MATCH = 'REGULAR_EXPRESSION'
152
- LOWER = 'LOWER'
153
- EQUAL = 'EQUAL'
154
- GREATER = 'GREATER'
155
- IS_TRUE = 'TRUE'
156
- IS_FALSE = 'FALSE'
157
- AMONG_VALUES = 'AMONG_VALUES'
158
- ANY = 'ANY'
159
- end
160
136
  end
161
137
  end
@@ -3,7 +3,7 @@
3
3
  module Kameleoon
4
4
  # Utils is a helper module for project
5
5
  module Utils
6
- ALPHA_NUMERIC_CHARS = 'abcdef0123456789'
6
+ ALPHA_NUMERIC_CHARS = 'ABCDEF0123456789'
7
7
 
8
8
  def self.in_seconds(days)
9
9
  days * 60 * 60 * 24
@@ -1,5 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kameleoon
4
- VERSION = '2.1.0'
4
+ SDK_NAME = 'RUBY'
5
+ SDK_VERSION = '2.1.1'
6
+
7
+ # SdkManager is a helper method for fetching / obtaining version of SDK from string
8
+ class SdkVersion
9
+ def self.get_version_components(version_string)
10
+ versions = [0, 0, 0]
11
+
12
+ version_parts = version_string.split('.')
13
+ version_parts.each_with_index do |part, i|
14
+ versions[i] = Integer(part)
15
+ rescue ArgumentError
16
+ puts "Invalid version component, index: #{i}, value: #{part}"
17
+ return nil
18
+ end
19
+ versions
20
+ end
21
+
22
+ def self.get_float_version(version_string)
23
+ version_components = get_version_components(version_string)
24
+
25
+ return Float::NAN if version_components.nil?
26
+
27
+ major = version_components[0]
28
+ minor = version_components[1]
29
+ "#{major}.#{minor}".to_f
30
+ end
31
+ end
5
32
  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: 2.1.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kameleoon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-20 00:00:00.000000000 Z
11
+ date: 2023-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -84,10 +84,20 @@ files:
84
84
  - lib/kameleoon/configuration/variation.rb
85
85
  - lib/kameleoon/configuration/variation_exposition.rb
86
86
  - lib/kameleoon/cookie.rb
87
- - lib/kameleoon/data.rb
87
+ - lib/kameleoon/data/browser.rb
88
+ - lib/kameleoon/data/conversion.rb
89
+ - lib/kameleoon/data/custom_data.rb
90
+ - lib/kameleoon/data/data.rb
91
+ - lib/kameleoon/data/device.rb
92
+ - lib/kameleoon/data/page_view.rb
93
+ - lib/kameleoon/data/user_agent.rb
88
94
  - lib/kameleoon/exceptions.rb
89
95
  - lib/kameleoon/factory.rb
90
96
  - lib/kameleoon/hybrid/manager.rb
97
+ - lib/kameleoon/network/activity_event.rb
98
+ - lib/kameleoon/network/experiment_event.rb
99
+ - lib/kameleoon/network/uri_helper.rb
100
+ - lib/kameleoon/network/url_provider.rb
91
101
  - lib/kameleoon/real_time/real_time_configuration_service.rb
92
102
  - lib/kameleoon/real_time/real_time_event.rb
93
103
  - lib/kameleoon/real_time/sse_client.rb
@@ -100,9 +110,18 @@ files:
100
110
  - lib/kameleoon/storage/visitor_variation.rb
101
111
  - lib/kameleoon/targeting/condition.rb
102
112
  - lib/kameleoon/targeting/condition_factory.rb
113
+ - lib/kameleoon/targeting/conditions/browser_condition.rb
114
+ - lib/kameleoon/targeting/conditions/conversion_condition.rb
103
115
  - lib/kameleoon/targeting/conditions/custom_datum.rb
116
+ - lib/kameleoon/targeting/conditions/device_condition.rb
104
117
  - lib/kameleoon/targeting/conditions/exclusive_experiment.rb
118
+ - lib/kameleoon/targeting/conditions/page_title_condition.rb
119
+ - lib/kameleoon/targeting/conditions/page_url_condition.rb
120
+ - lib/kameleoon/targeting/conditions/sdk_language_condition.rb
121
+ - lib/kameleoon/targeting/conditions/string_value_condition.rb
105
122
  - lib/kameleoon/targeting/conditions/target_experiment.rb
123
+ - lib/kameleoon/targeting/conditions/unknown_condition.rb
124
+ - lib/kameleoon/targeting/conditions/visitor_code_condition.rb
106
125
  - lib/kameleoon/targeting/models.rb
107
126
  - lib/kameleoon/targeting/tree_builder.rb
108
127
  - lib/kameleoon/utils.rb
@@ -1,175 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'kameleoon/exceptions'
4
-
5
- module Kameleoon
6
- NONCE_LENGTH = 16
7
-
8
- module DataType
9
- CUSTOM = 'CUSTOM'
10
- BROWSER = 'BROWSER'
11
- CONVERSION = 'CONVERSION'
12
- DEVICE = 'DEVICE'
13
- PAGE_VIEW = 'PAGE_VIEW'
14
- end
15
-
16
- module BrowserType
17
- CHROME = 0
18
- INTERNET_EXPLORER = 1
19
- FIREFOX = 2
20
- SAFARI = 3
21
- OPERA = 4
22
- OTHER = 5
23
- end
24
-
25
- module DeviceType
26
- PHONE = 'PHONE'
27
- TABLET = 'TABLET'
28
- DESKTOP = 'DESKTOP'
29
- end
30
-
31
- class Data
32
- attr_accessor :instance, :sent
33
-
34
- def initialize(*args)
35
- raise KameleoonError.new("Cannot initialise interface.")
36
- end
37
-
38
- def obtain_full_post_text_line
39
- raise KameleoonError.new("ToDo: implement this method.")
40
- end
41
-
42
- def encode(url)
43
- encoded_url = CGI.escape(url)
44
- encoded_url.gsub! "%27", "'"
45
- encoded_url.gsub! "%21", "!"
46
- encoded_url.gsub! "+", "%20"
47
- encoded_url.gsub! "%2A", "*"
48
- encoded_url.gsub! "%28", "("
49
- encoded_url.gsub! "%29", ")"
50
- encoded_url
51
- end
52
- end
53
-
54
- class CustomData < Data
55
- attr_reader :id, :values
56
-
57
- # @param [Integer] id Id of the custom data
58
- # @param [String] value Value of the custom data
59
- #
60
- # @overload
61
- # @param [Hash] hash Json value encoded in a hash.
62
- def initialize(arg0, *args)
63
- @instance = DataType::CUSTOM
64
- @sent = false
65
- if arg0.is_a?(Hash)
66
- hash = arg0
67
- id = hash['id']
68
- raise Kameleoon::Exception::NotFound.new('id') if id.nil?
69
- @id = id.to_s
70
- value = hash['value']
71
- values = hash['values']
72
- raise Kameleoon::Exception::NotFound.new('values') if values.nil? && value.nil?
73
- if values.nil?
74
- @values = [value]
75
- else
76
- @values = values.dup
77
- @values.append(value) unless value.nil?
78
- end
79
- else
80
- @id = arg0.to_s
81
- @values = args
82
- end
83
- end
84
-
85
- def obtain_full_post_text_line
86
- return '' if @values.empty?
87
-
88
- str_values = "[[\"#{@values.join('",1],["')}\",1]]"
89
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
90
- "eventType=customData&index=#{@id}&valueToCount=#{encode(str_values)}&overwrite=true&nonce=#{nonce}"
91
- end
92
- end
93
-
94
- class Browser < Data
95
- attr_accessor :browser
96
-
97
- # @param [BrowserType] browser_type Browser type, can be: CHROME, INTERNET_EXPLORER, FIREFOX, SAFARI, OPERA, OTHER
98
- def initialize(browser_type)
99
- @instance = DataType::BROWSER
100
- @sent = false
101
- @browser = browser_type
102
- end
103
-
104
- def obtain_full_post_text_line
105
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
106
- "eventType=staticData&browserIndex=" + @browser.to_s + "&nonce=" + nonce
107
- end
108
- end
109
-
110
- class PageView < Data
111
- attr_accessor :url, :title, :referrer
112
-
113
- # @param [String] url Url of the page
114
- # @param [String] title Title of the page
115
- # @param [Array] referrers Optional field - Referrer ids
116
- def initialize(url, title, referrers = nil)
117
- @instance = DataType::PAGE_VIEW
118
- @sent = false
119
- @url = url
120
- @title = title
121
- @referrers = referrers
122
- end
123
-
124
- def obtain_full_post_text_line
125
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
126
- referrer_text = ''
127
- unless @referrers.nil?
128
- referrer_text = "&referrersIndices=" + @referrers.to_s
129
- end
130
- "eventType=page&href=" + encode(@url) + "&title=" + @title + referrer_text + "&nonce=" + nonce
131
- end
132
- end
133
-
134
- class Conversion < Data
135
- attr_accessor :goal_id, :revenue, :negative
136
-
137
- # @param [Integer] goal_id Id of the goal associated to the conversion
138
- # @param [Float] revenue Optional field - Revenue associated to the conversion.
139
- # @param [Boolean] negative Optional field - If the revenue is negative. By default it's positive.
140
- def initialize(goal_id, revenue = 0.0, negative = false)
141
- @instance = DataType::CONVERSION
142
- @sent = false
143
- @goal_id = goal_id
144
- @revenue = revenue
145
- @negative = negative
146
- end
147
-
148
- def obtain_full_post_text_line
149
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
150
- "eventType=conversion&goalId=" + @goal_id.to_s + "&revenue=" + @revenue.to_s + "&negative=" + @negative.to_s + "&nonce=" + nonce
151
- end
152
- end
153
-
154
- # Device uses for sending deviceType parameter for tracking calls
155
- class Device < Data
156
- def initialize(device_type)
157
- @instance = DataType::DEVICE
158
- @sent = false
159
- @device_type = device_type
160
- end
161
-
162
- def obtain_full_post_text_line
163
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
164
- "eventType=staticData&deviceType=#{@device_type}&nonce=#{nonce}"
165
- end
166
- end
167
-
168
- # UserAgent uses for changing User-Agent header for tracking calls
169
- class UserAgent
170
- attr_accessor :value
171
- def initialize(value)
172
- @value = value
173
- end
174
- end
175
- end