kameleoon-client-ruby 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kameleoon/client.rb +105 -151
- data/lib/kameleoon/configuration/rule.rb +1 -1
- data/lib/kameleoon/data/browser.rb +39 -0
- data/lib/kameleoon/data/conversion.rb +33 -0
- data/lib/kameleoon/data/custom_data.rb +60 -0
- data/lib/kameleoon/data/data.rb +38 -0
- data/lib/kameleoon/data/device.rb +31 -0
- data/lib/kameleoon/data/page_view.rb +34 -0
- data/lib/kameleoon/data/user_agent.rb +14 -0
- data/lib/kameleoon/network/activity_event.rb +31 -0
- data/lib/kameleoon/network/content_type.rb +11 -0
- data/lib/kameleoon/network/experiment_event.rb +35 -0
- data/lib/kameleoon/network/method.rb +10 -0
- data/lib/kameleoon/network/net_provider.rb +91 -0
- data/lib/kameleoon/network/network_manager.rb +114 -0
- data/lib/kameleoon/network/request.rb +20 -0
- data/lib/kameleoon/network/response.rb +30 -0
- data/lib/kameleoon/network/uri_helper.rb +37 -0
- data/lib/kameleoon/network/url_provider.rb +71 -0
- data/lib/kameleoon/targeting/condition.rb +40 -11
- data/lib/kameleoon/targeting/condition_factory.rb +35 -12
- data/lib/kameleoon/targeting/conditions/browser_condition.rb +71 -0
- data/lib/kameleoon/targeting/conditions/conversion_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/custom_datum.rb +60 -65
- data/lib/kameleoon/targeting/conditions/device_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -12
- data/lib/kameleoon/targeting/conditions/page_title_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/page_url_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +65 -0
- data/lib/kameleoon/targeting/conditions/string_value_condition.rb +40 -0
- data/lib/kameleoon/targeting/conditions/target_experiment.rb +4 -8
- data/lib/kameleoon/targeting/conditions/unknown_condition.rb +15 -0
- data/lib/kameleoon/targeting/conditions/visitor_code_condition.rb +16 -0
- data/lib/kameleoon/targeting/models.rb +0 -24
- data/lib/kameleoon/utils.rb +1 -1
- data/lib/kameleoon/version.rb +28 -1
- metadata +28 -4
- data/lib/kameleoon/data.rb +0 -175
- data/lib/kameleoon/request.rb +0 -90
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'kameleoon/network/uri_helper'
|
5
|
+
require_relative 'data'
|
6
|
+
|
7
|
+
module Kameleoon
|
8
|
+
# Represents page view data for tracking calls
|
9
|
+
class PageView < Data
|
10
|
+
attr_reader :url, :title, :referrer
|
11
|
+
|
12
|
+
# @param [String] url Url of the page
|
13
|
+
# @param [String] title Title of the page
|
14
|
+
# @param [Array] referrers Optional field - Referrer ids
|
15
|
+
def initialize(url, title, referrers = nil)
|
16
|
+
super(DataType::PAGE_VIEW)
|
17
|
+
@url = url || ''
|
18
|
+
@title = title || ''
|
19
|
+
@referrers = referrers.instance_of?(Integer) ? [referrers] : referrers
|
20
|
+
end
|
21
|
+
|
22
|
+
def obtain_full_post_text_line
|
23
|
+
params = {
|
24
|
+
eventType: 'page',
|
25
|
+
href: @url,
|
26
|
+
title: @title,
|
27
|
+
nonce: nonce
|
28
|
+
}
|
29
|
+
params[:referrersIndices] = "[#{@referrers.each(&:to_s).join(',')}]" if
|
30
|
+
!@referrers.nil? && !@referrers.empty?
|
31
|
+
Kameleoon::Network::UriHelper.encode_query(params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'kameleoon/data/data'
|
5
|
+
require 'kameleoon/utils'
|
6
|
+
require 'kameleoon/network/uri_helper'
|
7
|
+
|
8
|
+
module Kameleoon
|
9
|
+
module Network
|
10
|
+
##
|
11
|
+
# ActivityEvent represents an activity tracking event.
|
12
|
+
class ActivityEvent
|
13
|
+
EVENT_TYPE = 'activity'
|
14
|
+
|
15
|
+
attr_accessor :sent
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@sent = false
|
19
|
+
@nonce = Kameleoon::Utils.generate_random_string(Kameleoon::NONCE_LENGTH)
|
20
|
+
end
|
21
|
+
|
22
|
+
def obtain_full_post_text_line
|
23
|
+
params = {
|
24
|
+
eventType: EVENT_TYPE,
|
25
|
+
nonce: @nonce
|
26
|
+
}
|
27
|
+
UriHelper.encode_query(params)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'kameleoon/data/data'
|
5
|
+
require 'kameleoon/utils'
|
6
|
+
require 'kameleoon/network/uri_helper'
|
7
|
+
|
8
|
+
module Kameleoon
|
9
|
+
module Network
|
10
|
+
##
|
11
|
+
# ExperimentEvent represents an experiment tracking event.
|
12
|
+
class ExperimentEvent
|
13
|
+
EVENT_TYPE = 'experiment'
|
14
|
+
|
15
|
+
attr_accessor :sent
|
16
|
+
|
17
|
+
def initialize(experiment_id, variation_id)
|
18
|
+
@sent = false
|
19
|
+
@experiment_id = experiment_id
|
20
|
+
@variation_id = variation_id
|
21
|
+
@nonce = Kameleoon::Utils.generate_random_string(Kameleoon::NONCE_LENGTH)
|
22
|
+
end
|
23
|
+
|
24
|
+
def obtain_full_post_text_line
|
25
|
+
params = {
|
26
|
+
eventType: EVENT_TYPE,
|
27
|
+
id: @experiment_id,
|
28
|
+
variationId: @variation_id,
|
29
|
+
nonce: @nonce
|
30
|
+
}
|
31
|
+
UriHelper.encode_query(params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'em-synchrony/em-http'
|
4
|
+
require 'net/http'
|
5
|
+
require 'kameleoon/version'
|
6
|
+
require 'kameleoon/network/response'
|
7
|
+
require 'kameleoon/exceptions'
|
8
|
+
|
9
|
+
module Kameleoon
|
10
|
+
module Network
|
11
|
+
class NetProvider
|
12
|
+
def make_request(_request)
|
13
|
+
raise KameleoonError, 'Call of not implemented method!'
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def collect_headers(request)
|
19
|
+
headers = { 'Content-Type': request.content_type }
|
20
|
+
headers['User-Agent'] = request.user_agent unless request.user_agent.nil?
|
21
|
+
headers
|
22
|
+
end
|
23
|
+
|
24
|
+
def unknown_method_response(method, request)
|
25
|
+
Response.new("Unknown request method '#{method}'", nil, nil, request)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class EMNetProvider < NetProvider
|
30
|
+
def make_request(request)
|
31
|
+
connetion_options = {
|
32
|
+
tls: { verify_peer: false },
|
33
|
+
connect_timeout: request.timeout,
|
34
|
+
inactivity_timeout: request.timeout
|
35
|
+
}
|
36
|
+
headers = collect_headers(request)
|
37
|
+
request_options = { head: headers, body: request.data }
|
38
|
+
begin
|
39
|
+
case request.method
|
40
|
+
when Method::POST
|
41
|
+
EventMachine::HttpRequest.new(request.url, connetion_options).apost(request_options)
|
42
|
+
when Method::GET
|
43
|
+
EventMachine::HttpRequest.new(request.url, connetion_options).aget(request_options)
|
44
|
+
else
|
45
|
+
dfr = DeferrableResponse.new
|
46
|
+
dfr.response = unknown_method_response(request.method, request)
|
47
|
+
dfr
|
48
|
+
end
|
49
|
+
rescue => e
|
50
|
+
dfr = DeferrableResponse.new
|
51
|
+
dfr.response = Response.new(e, nil, nil, request)
|
52
|
+
dfr
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.em_resp_to_response(request, resp)
|
57
|
+
return resp if resp.is_a?(Response)
|
58
|
+
|
59
|
+
Response.new(nil, resp.response_header.status, resp.response, request)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class SyncNetProvider < NetProvider
|
64
|
+
def make_request(request)
|
65
|
+
resp = nil
|
66
|
+
begin
|
67
|
+
case request.method
|
68
|
+
when Method::GET
|
69
|
+
req = Net::HTTP::Get.new(request.url)
|
70
|
+
when Method::POST
|
71
|
+
req = Net::HTTP::Post.new(request.url)
|
72
|
+
req.body = request.data
|
73
|
+
else
|
74
|
+
return unknown_method_response(request.method, request)
|
75
|
+
end
|
76
|
+
timeout = request.timeout.to_f / 1000.0
|
77
|
+
headers = collect_headers(request)
|
78
|
+
headers.each { |k, v| req[k] = v }
|
79
|
+
uri = URI(request.url)
|
80
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, open_timeout: timeout,
|
81
|
+
read_timeout: timeout, ssl_timeout: timeout) do |http|
|
82
|
+
resp = http.request(req)
|
83
|
+
end
|
84
|
+
rescue => e
|
85
|
+
return Response.new(e, nil, nil, request)
|
86
|
+
end
|
87
|
+
Response.new(nil, resp.code.to_i, resp.body, request)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'em-synchrony'
|
4
|
+
require 'kameleoon/network/content_type'
|
5
|
+
require 'kameleoon/network/method'
|
6
|
+
require 'kameleoon/network/request'
|
7
|
+
require 'kameleoon/network/net_provider'
|
8
|
+
|
9
|
+
module Kameleoon
|
10
|
+
module Network
|
11
|
+
##
|
12
|
+
# NetworkManager is used to make API calls.
|
13
|
+
class NetworkManager
|
14
|
+
FETCH_CONFIGURATION_ATTEMPT_NUMBER = 4
|
15
|
+
TRACKING_CALL_ATTEMPT_NUMBER = 4
|
16
|
+
TRACKING_CALL_RETRY_DELAY = 5.0 # in seconds
|
17
|
+
|
18
|
+
attr_reader :environment, :default_timeout, :url_provider
|
19
|
+
|
20
|
+
def initialize(environment, default_timeout, url_provider, log_func = nil)
|
21
|
+
@environment = environment
|
22
|
+
@default_timeout = default_timeout
|
23
|
+
@url_provider = url_provider
|
24
|
+
@em_net_provider = EMNetProvider.new
|
25
|
+
@sync_net_provider = SyncNetProvider.new
|
26
|
+
@log_func = log_func
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_configuration(timestamp = nil, timeout = nil)
|
30
|
+
url = @url_provider.make_configuration_url(@environment, timestamp)
|
31
|
+
timeout = ensure_timeout(timeout)
|
32
|
+
request = Request.new(Method::GET, url, ContentType::JSON, timeout)
|
33
|
+
attempts_left = FETCH_CONFIGURATION_ATTEMPT_NUMBER
|
34
|
+
while attempts_left.positive?
|
35
|
+
em_resp = EM::Synchrony.sync(@em_net_provider.make_request(request))
|
36
|
+
response = EMNetProvider.em_resp_to_response(request, em_resp)
|
37
|
+
result = handle_response(response)
|
38
|
+
return result if result
|
39
|
+
|
40
|
+
attempts_left -= 1
|
41
|
+
end
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_remote_data(key, timeout = nil)
|
46
|
+
url = @url_provider.make_api_data_get_request_url(key)
|
47
|
+
timeout = ensure_timeout(timeout)
|
48
|
+
request = Request.new(Method::GET, url, ContentType::JSON, timeout)
|
49
|
+
response = @sync_net_provider.make_request(request)
|
50
|
+
handle_response(response)
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_remote_visitor_data(visitor_code, timeout = nil)
|
54
|
+
url = @url_provider.make_visitor_data_get_url(visitor_code)
|
55
|
+
timeout = ensure_timeout(timeout)
|
56
|
+
request = Request.new(Method::GET, url, ContentType::JSON, timeout)
|
57
|
+
response = @sync_net_provider.make_request(request)
|
58
|
+
handle_response(response)
|
59
|
+
end
|
60
|
+
|
61
|
+
def send_tracking_data(visitor_code, lines, user_agent, timeout = nil)
|
62
|
+
return if lines.nil? || lines.empty?
|
63
|
+
|
64
|
+
url = @url_provider.make_tracking_url(visitor_code)
|
65
|
+
timeout = ensure_timeout(timeout)
|
66
|
+
data = (lines.map(&:obtain_full_post_text_line).join("\n") || '').encode('UTF-8')
|
67
|
+
request = Request.new(Method::POST, url, ContentType::TEXT, timeout, user_agent, data)
|
68
|
+
Thread.new do
|
69
|
+
attempts_left = TRACKING_CALL_ATTEMPT_NUMBER
|
70
|
+
loop do
|
71
|
+
response = @sync_net_provider.make_request(request)
|
72
|
+
if handle_response(response) != false
|
73
|
+
lines.each { |line| line.sent = true }
|
74
|
+
break
|
75
|
+
end
|
76
|
+
attempts_left -= 1
|
77
|
+
break unless attempts_left.positive?
|
78
|
+
|
79
|
+
delay(TRACKING_CALL_RETRY_DELAY)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def log_failure(request, message)
|
87
|
+
return if @log_func.nil?
|
88
|
+
|
89
|
+
premsg = "#{request.method} call '#{request.url}' "
|
90
|
+
premsg += request.data.nil? ? 'failed' : "(data '#{request.data}') failed"
|
91
|
+
@log_func.call("#{premsg}: #{message}")
|
92
|
+
end
|
93
|
+
|
94
|
+
def delay(period)
|
95
|
+
sleep(period)
|
96
|
+
end
|
97
|
+
|
98
|
+
def ensure_timeout(timeout)
|
99
|
+
timeout.nil? ? @default_timeout : timeout
|
100
|
+
end
|
101
|
+
|
102
|
+
def handle_response(response)
|
103
|
+
if !response.error.nil?
|
104
|
+
log_failure(response.request, "Error occurred during request: #{response.error}")
|
105
|
+
elsif response.code / 100 != 2
|
106
|
+
log_failure(response.request, "Received unexpected status code '#{response.code}'")
|
107
|
+
else
|
108
|
+
return response.body
|
109
|
+
end
|
110
|
+
false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
module Network
|
5
|
+
##
|
6
|
+
# Request represents HTTP request.
|
7
|
+
class Request
|
8
|
+
attr_reader :method, :url, :content_type, :timeout, :user_agent, :data
|
9
|
+
|
10
|
+
def initialize(method, url, content_type, timeout, user_agent = nil, data = nil)
|
11
|
+
@method = method
|
12
|
+
@url = url
|
13
|
+
@content_type = content_type
|
14
|
+
@timeout = timeout
|
15
|
+
@user_agent = user_agent
|
16
|
+
@data = !data.nil? && data.is_a?(String) ? data.encode('UTF-8') : data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
module Network
|
5
|
+
##
|
6
|
+
# Response represents HTTP response.
|
7
|
+
class Response
|
8
|
+
attr_reader :error, :code, :body, :request
|
9
|
+
|
10
|
+
def initialize(error, code, body, request)
|
11
|
+
@error = error
|
12
|
+
@code = code
|
13
|
+
@body = body
|
14
|
+
@request = request
|
15
|
+
end
|
16
|
+
|
17
|
+
def success?
|
18
|
+
@error.nil? && (@code / 100 == 2)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class DeferrableResponse < EventMachine::DefaultDeferrable
|
23
|
+
attr_writer :response
|
24
|
+
|
25
|
+
def callback(&blk)
|
26
|
+
blk.call(@response)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
module Network
|
8
|
+
##
|
9
|
+
# UriHelper contains functions which helps working with URIs.
|
10
|
+
module UriHelper
|
11
|
+
def self.encode_uri(uri)
|
12
|
+
encoded = CGI.escape(uri)
|
13
|
+
encoded.gsub!(/%21|%27|%28|%29|%2A|\+/,
|
14
|
+
'%21' => '!',
|
15
|
+
'%27' => "'",
|
16
|
+
'%28' => '(',
|
17
|
+
'%29' => ')',
|
18
|
+
'%2A' => '*',
|
19
|
+
'+' => '%20')
|
20
|
+
encoded
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.encode_query(params)
|
24
|
+
params.delete_if { |_k, v| v.nil? || (v == '') }
|
25
|
+
encoded = URI.encode_www_form(params)
|
26
|
+
encoded.gsub!(/%21|%27|%28|%29|%7E|\+/,
|
27
|
+
'%21' => '!',
|
28
|
+
'%27' => "'",
|
29
|
+
'%28' => '(',
|
30
|
+
'%29' => ')',
|
31
|
+
'%7E' => '~',
|
32
|
+
'+' => '%20')
|
33
|
+
encoded
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kameleoon/version'
|
4
|
+
require 'kameleoon/network/uri_helper'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
module Network
|
8
|
+
##
|
9
|
+
# UrlProvider is used as a source of URLs for network calls.
|
10
|
+
class UrlProvider
|
11
|
+
TRACKING_PATH = '/visit/events'
|
12
|
+
VISITOR_DATA_PATH = '/visit/visitor'
|
13
|
+
GET_DATA_PATH = '/map/map'
|
14
|
+
POST_DATA_PATH = '/map/maps'
|
15
|
+
CONFIGURATION_API_URL = 'https://client-config.kameleoon.com/mobile'
|
16
|
+
RT_CONFIGURATION_URL = 'https://events.kameleoon.com:8110/sse'
|
17
|
+
|
18
|
+
DEFAULT_DATA_API_URL = 'https://data.kameleoon.io'
|
19
|
+
TEST_DATA_API_URL = 'https://data.kameleoon.net'
|
20
|
+
|
21
|
+
attr_reader :site_code, :data_api_url
|
22
|
+
|
23
|
+
def initialize(site_code, data_api_url)
|
24
|
+
@site_code = site_code
|
25
|
+
@data_api_url = data_api_url
|
26
|
+
end
|
27
|
+
|
28
|
+
def make_tracking_url(visitor_code)
|
29
|
+
params = {
|
30
|
+
sdkName: SDK_NAME,
|
31
|
+
sdkVersion: SDK_VERSION,
|
32
|
+
siteCode: @site_code,
|
33
|
+
visitorCode: visitor_code
|
34
|
+
}
|
35
|
+
"#{@data_api_url}#{TRACKING_PATH}?#{UriHelper.encode_query(params)}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def make_visitor_data_get_url(visitor_code)
|
39
|
+
params = {
|
40
|
+
siteCode: @site_code,
|
41
|
+
visitorCode: visitor_code,
|
42
|
+
currentVisit: true,
|
43
|
+
maxNumberPreviousVisits: 1,
|
44
|
+
customData: true,
|
45
|
+
version: 0
|
46
|
+
}
|
47
|
+
"#{@data_api_url}#{VISITOR_DATA_PATH}?#{UriHelper.encode_query(params)}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def make_api_data_get_request_url(key)
|
51
|
+
params = {
|
52
|
+
siteCode: @site_code,
|
53
|
+
key: key
|
54
|
+
}
|
55
|
+
"#{@data_api_url}#{GET_DATA_PATH}?#{UriHelper.encode_query(params)}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def make_configuration_url(environment = nil, timestamp = nil)
|
59
|
+
params = { siteCode: @site_code }
|
60
|
+
params[:environment] = environment unless environment.nil?
|
61
|
+
params[:ts] = timestamp unless timestamp.nil?
|
62
|
+
"#{CONFIGURATION_API_URL}?#{UriHelper.encode_query(params)}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def make_real_time_url
|
66
|
+
params = { siteCode: @site_code }
|
67
|
+
"#{RT_CONFIGURATION_URL}?#{UriHelper.encode_query(params)}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,28 +1,57 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'kameleoon/exceptions'
|
2
3
|
|
3
4
|
module Kameleoon
|
4
5
|
# @api private
|
5
6
|
module Targeting
|
7
|
+
module ConditionType
|
8
|
+
CUSTOM_DATUM = 'CUSTOM_DATUM'
|
9
|
+
TARGET_EXPERIMENT = 'TARGET_EXPERIMENT'
|
10
|
+
EXCLUSIVE_EXPERIMENT = 'EXCLUSIVE_EXPERIMENT'
|
11
|
+
PAGE_URL = 'PAGE_URL'
|
12
|
+
PAGE_TITLE = 'PAGE_TITLE'
|
13
|
+
VISITOR_CODE = 'VISITOR_CODE'
|
14
|
+
DEVICE_TYPE = 'DEVICE_TYPE'
|
15
|
+
BROWSER = 'BROWSER'
|
16
|
+
SDK_LANGUAGE = 'SDK_LANGUAGE'
|
17
|
+
CONVERSIONS = 'CONVERSIONS'
|
18
|
+
end
|
19
|
+
|
20
|
+
module Operator
|
21
|
+
UNDEFINED = 'UNDEFINED'
|
22
|
+
CONTAINS = 'CONTAINS'
|
23
|
+
EXACT = 'EXACT'
|
24
|
+
REGULAR_EXPRESSION = 'REGULAR_EXPRESSION'
|
25
|
+
LOWER = 'LOWER'
|
26
|
+
EQUAL = 'EQUAL'
|
27
|
+
GREATER = 'GREATER'
|
28
|
+
IS_TRUE = 'TRUE'
|
29
|
+
IS_FALSE = 'FALSE'
|
30
|
+
AMONG_VALUES = 'AMONG_VALUES'
|
31
|
+
ANY = 'ANY'
|
32
|
+
UNKNOWN = 'UNKNOWN'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Base class for all targeting conditions
|
6
36
|
class Condition
|
7
|
-
|
37
|
+
attr_reader :type, :include
|
8
38
|
|
9
39
|
def initialize(json_condition)
|
10
|
-
if json_condition['targetingType'].nil?
|
11
|
-
raise Exception::NotFound.new('targetingType'), 'targetingType missed'
|
12
|
-
end
|
40
|
+
raise Exception::NotFound.new('targetingType'), 'targetingType missed' if json_condition['targetingType'].nil?
|
13
41
|
|
14
42
|
@type = json_condition['targetingType']
|
15
|
-
|
16
|
-
if json_condition['include'].nil? && json_condition['isInclude'].nil?
|
17
|
-
raise Exception::NotFound.new('include / isInclude missed'), 'include / isInclude missed'
|
18
|
-
end
|
19
|
-
|
20
|
-
@include = json_condition['include'] || json_condition['isInclude']
|
43
|
+
@include = json_condition['isInclude'].nil? ? true : json_condition['isInclude']
|
21
44
|
end
|
22
45
|
|
23
|
-
def check(
|
46
|
+
def check(_data)
|
24
47
|
raise 'Abstract method `check` call'
|
25
48
|
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def get_last_targeting_data(list_data, data_type)
|
53
|
+
list_data.select { |data| data.instance == data_type }.last
|
54
|
+
end
|
26
55
|
end
|
27
56
|
end
|
28
57
|
end
|
@@ -1,22 +1,45 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative 'conditions/custom_datum'
|
2
|
+
require_relative 'conditions/target_experiment'
|
3
|
+
require_relative 'conditions/exclusive_experiment'
|
4
|
+
require_relative 'conditions/page_title_condition'
|
5
|
+
require_relative 'conditions/page_url_condition'
|
6
|
+
require_relative 'conditions/visitor_code_condition'
|
7
|
+
require_relative 'conditions/device_condition'
|
8
|
+
require_relative 'conditions/conversion_condition'
|
9
|
+
require_relative 'conditions/browser_condition'
|
10
|
+
require_relative 'conditions/sdk_language_condition'
|
11
|
+
require_relative 'conditions/unknown_condition'
|
4
12
|
|
5
13
|
module Kameleoon
|
6
|
-
|
14
|
+
# @api private
|
7
15
|
module Targeting
|
16
|
+
# Module for create different targeting conditions
|
8
17
|
module ConditionFactory
|
9
18
|
def get_condition(condition_json)
|
10
|
-
condition = nil
|
11
19
|
case condition_json['targetingType']
|
12
|
-
when ConditionType::CUSTOM_DATUM
|
13
|
-
|
14
|
-
when ConditionType::TARGET_EXPERIMENT
|
15
|
-
|
16
|
-
when ConditionType::EXCLUSIVE_EXPERIMENT
|
17
|
-
|
20
|
+
when ConditionType::CUSTOM_DATUM
|
21
|
+
CustomDatum.new(condition_json)
|
22
|
+
when ConditionType::TARGET_EXPERIMENT
|
23
|
+
TargetExperiment.new(condition_json)
|
24
|
+
when ConditionType::EXCLUSIVE_EXPERIMENT
|
25
|
+
ExclusiveExperiment.new(condition_json)
|
26
|
+
when ConditionType::PAGE_URL
|
27
|
+
PageUrlCondition.new(condition_json)
|
28
|
+
when ConditionType::PAGE_TITLE
|
29
|
+
PageTitleCondition.new(condition_json)
|
30
|
+
when ConditionType::VISITOR_CODE
|
31
|
+
VisitorCodeCondition.new(condition_json)
|
32
|
+
when ConditionType::DEVICE_TYPE
|
33
|
+
DeviceCondition.new(condition_json)
|
34
|
+
when ConditionType::CONVERSIONS
|
35
|
+
ConversionCondition.new(condition_json)
|
36
|
+
when ConditionType::BROWSER
|
37
|
+
BrowserCondition.new(condition_json)
|
38
|
+
when ConditionType::SDK_LANGUAGE
|
39
|
+
SdkLanguageCondition.new(condition_json)
|
40
|
+
else
|
41
|
+
UnknownCondition.new(condition_json)
|
18
42
|
end
|
19
|
-
condition
|
20
43
|
end
|
21
44
|
end
|
22
45
|
end
|