kameleoon-client-ruby 2.1.0 → 2.1.1
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 +79 -133
- data/lib/kameleoon/configuration/rule.rb +1 -1
- data/lib/kameleoon/data/browser.rb +33 -0
- data/lib/kameleoon/data/conversion.rb +26 -0
- data/lib/kameleoon/data/custom_data.rb +53 -0
- data/lib/kameleoon/data/data.rb +35 -0
- data/lib/kameleoon/data/device.rb +26 -0
- data/lib/kameleoon/data/page_view.rb +31 -0
- data/lib/kameleoon/data/user_agent.rb +14 -0
- data/lib/kameleoon/network/activity_event.rb +31 -0
- data/lib/kameleoon/network/experiment_event.rb +35 -0
- data/lib/kameleoon/network/uri_helper.rb +36 -0
- data/lib/kameleoon/network/url_provider.rb +71 -0
- data/lib/kameleoon/request.rb +5 -19
- 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 +22 -3
- data/lib/kameleoon/data.rb +0 -175
@@ -0,0 +1,36 @@
|
|
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
|
+
encoded = URI.encode_www_form(params)
|
25
|
+
encoded.gsub!(/%21|%27|%28|%29|%7E|\+/,
|
26
|
+
'%21' => '!',
|
27
|
+
'%27' => "'",
|
28
|
+
'%28' => '(',
|
29
|
+
'%29' => ')',
|
30
|
+
'%7E' => '~',
|
31
|
+
'+' => '%20')
|
32
|
+
encoded
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
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
|
data/lib/kameleoon/request.rb
CHANGED
@@ -7,27 +7,24 @@ module Kameleoon
|
|
7
7
|
module Request
|
8
8
|
protected
|
9
9
|
|
10
|
-
API_URL = 'https://api.kameleoon.com'.freeze
|
11
|
-
CLIENT_CONFIG_URL = 'https://client-config.kameleoon.com'.freeze
|
12
|
-
|
13
10
|
module Method
|
14
11
|
GET = 'get'.freeze
|
15
12
|
POST = 'post'.freeze
|
16
13
|
end
|
17
14
|
|
18
|
-
def get(request_options, url
|
15
|
+
def get(request_options, url, connexion_options = {})
|
19
16
|
request(Method::GET, request_options, url, connexion_options)
|
20
17
|
end
|
21
18
|
|
22
|
-
def post(request_options, url
|
19
|
+
def post(request_options, url, connexion_options = {})
|
23
20
|
request(Method::POST, request_options, url, connexion_options)
|
24
21
|
end
|
25
22
|
|
26
|
-
def get_sync(url
|
23
|
+
def get_sync(url, connexion_options = {})
|
27
24
|
request_sync(Method::GET, url, connexion_options, {})
|
28
25
|
end
|
29
26
|
|
30
|
-
def post_sync(request_options, url
|
27
|
+
def post_sync(request_options, url, connexion_options = {})
|
31
28
|
request_sync(Method::POST, url, connexion_options, request_options)
|
32
29
|
end
|
33
30
|
|
@@ -35,7 +32,6 @@ module Kameleoon
|
|
35
32
|
|
36
33
|
def request(method, request_options, url, connexion_options)
|
37
34
|
connexion_options[:tls] = { verify_peer: false }
|
38
|
-
add_user_agent(request_options)
|
39
35
|
case method
|
40
36
|
when Method::POST then
|
41
37
|
return EventMachine::HttpRequest.new(url, connexion_options).apost request_options
|
@@ -49,7 +45,6 @@ module Kameleoon
|
|
49
45
|
|
50
46
|
def request_sync(method, url, connexion_options, request_options)
|
51
47
|
request_options = {} if request_options.nil?
|
52
|
-
add_user_agent(request_options)
|
53
48
|
case method
|
54
49
|
when Method::GET then
|
55
50
|
uri = URI(url)
|
@@ -60,7 +55,7 @@ module Kameleoon
|
|
60
55
|
uri = URI.parse(url)
|
61
56
|
http = Net::HTTP.new(uri.host, uri.port)
|
62
57
|
http.use_ssl = true
|
63
|
-
request = Net::HTTP::Post.new(
|
58
|
+
request = Net::HTTP::Post.new(uri, initheader = request_options[:head])
|
64
59
|
request.body = request_options[:body]
|
65
60
|
response = http.request(request)
|
66
61
|
response
|
@@ -77,14 +72,5 @@ module Kameleoon
|
|
77
72
|
def successful_sync?(response)
|
78
73
|
!response.nil? && response != false && response.is_a?(Net::HTTPSuccess)
|
79
74
|
end
|
80
|
-
|
81
|
-
def add_user_agent(request_options)
|
82
|
-
sdk_version = "sdk/ruby/#{Kameleoon::VERSION}"
|
83
|
-
if request_options[:head].nil?
|
84
|
-
request_options[:head] = { 'Kameleoon-Client' => sdk_version }
|
85
|
-
else
|
86
|
-
request_options[:head].store('Kameleoon-Client', sdk_version)
|
87
|
-
end
|
88
|
-
end
|
89
75
|
end
|
90
76
|
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
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kameleoon/data/browser'
|
4
|
+
require 'kameleoon/version'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
# @api private
|
8
|
+
module Targeting
|
9
|
+
|
10
|
+
CHROME = 'CHROME'
|
11
|
+
INTERNET_EXPLORER = 'IE'
|
12
|
+
FIREFOX = 'FIREFOX'
|
13
|
+
SAFARI = 'SAFARI'
|
14
|
+
OPERA = 'OPERA'
|
15
|
+
|
16
|
+
# BrowserCondition is a condition for checking targeting with browser's type and version
|
17
|
+
class BrowserCondition < Condition
|
18
|
+
def initialize(json_condition)
|
19
|
+
super(json_condition)
|
20
|
+
@browser_type = browser_index_from_name(json_condition['browser'])
|
21
|
+
@version = json_condition['version']
|
22
|
+
@version_match_type = json_condition['versionMatchType']
|
23
|
+
end
|
24
|
+
|
25
|
+
def check(list_data)
|
26
|
+
browser = get_last_targeting_data(list_data, Kameleoon::DataType::BROWSER)
|
27
|
+
browser && check_targeting(browser)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def check_targeting(browser)
|
33
|
+
return false if @browser_type != browser.type
|
34
|
+
|
35
|
+
return true if @version.nil?
|
36
|
+
|
37
|
+
version_number = SdkVersion.get_float_version(@version)
|
38
|
+
return false if version_number.nan?
|
39
|
+
|
40
|
+
case @version_match_type
|
41
|
+
when Operator::EQUAL
|
42
|
+
browser.version == version_number
|
43
|
+
when Operator::GREATER
|
44
|
+
browser.version > version_number
|
45
|
+
when Operator::LOWER
|
46
|
+
browser.version < version_number
|
47
|
+
else
|
48
|
+
puts "Unexpected comparing operation for Browser condition: #{@version_match_type}"
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def browser_index_from_name(name)
|
54
|
+
case name
|
55
|
+
when CHROME
|
56
|
+
BrowserType::CHROME
|
57
|
+
when INTERNET_EXPLORER
|
58
|
+
BrowserType::INTERNET_EXPLORER
|
59
|
+
when FIREFOX
|
60
|
+
BrowserType::FIREFOX
|
61
|
+
when SAFARI
|
62
|
+
BrowserType::SAFARI
|
63
|
+
when OPERA
|
64
|
+
BrowserType::OPERA
|
65
|
+
else
|
66
|
+
BrowserType::OTHER
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kameleoon/data/data'
|
4
|
+
|
5
|
+
module Kameleoon
|
6
|
+
# @api private
|
7
|
+
module Targeting
|
8
|
+
# ConversionCondition is a condition for checking targeting of conversions of visitor
|
9
|
+
class ConversionCondition < Condition
|
10
|
+
def initialize(json_condition)
|
11
|
+
super(json_condition)
|
12
|
+
@goal_id = json_condition['goalId']
|
13
|
+
end
|
14
|
+
|
15
|
+
def check(list_data)
|
16
|
+
conversion = get_last_targeting_data(list_data, Kameleoon::DataType::CONVERSION)
|
17
|
+
conversion && (@goal_id.nil? || @goal_id == conversion.goal_id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -11,90 +11,85 @@ module Kameleoon
|
|
11
11
|
class CustomDatum < Condition
|
12
12
|
include Kameleoon::Exception
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if json_condition['valueMatchType'].nil?
|
19
|
-
raise Exception::NotFound.new('valueMatchType'), 'valueMatchType missed'
|
14
|
+
class << self
|
15
|
+
def op_match(values, value)
|
16
|
+
re = Regexp.new(value.to_s)
|
17
|
+
values.any? { |v| re.match(v) }
|
20
18
|
end
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
@value = json_condition['value']
|
25
|
-
|
26
|
-
@type = ConditionType::CUSTOM_DATUM
|
27
|
-
|
28
|
-
if json_condition['include'].nil? && json_condition['isInclude'].nil?
|
29
|
-
raise Exception::NotFound.new('include / isInclude missed'), 'include / isInclude missed'
|
20
|
+
def op_contains(values, value)
|
21
|
+
values.any? { |v| v.to_s.include? value.to_s }
|
30
22
|
end
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
Operator::MATCH.to_s => method(:op_match),
|
36
|
-
Operator::CONTAINS.to_s => method(:op_contains),
|
37
|
-
Operator::EXACT.to_s => method(:op_exact),
|
38
|
-
Operator::EQUAL.to_s => method(:op_equal),
|
39
|
-
Operator::GREATER.to_s => method(:op_greater),
|
40
|
-
Operator::LOWER.to_s => method(:op_lower),
|
41
|
-
Operator::IS_TRUE.to_s => method(:op_is_true),
|
42
|
-
Operator::IS_FALSE.to_s => method(:op_is_false),
|
43
|
-
Operator::AMONG_VALUES.to_s => method(:op_among_values),
|
44
|
-
}[@operator]
|
45
|
-
end
|
24
|
+
def op_exact(values, value)
|
25
|
+
values.include? value.to_s
|
26
|
+
end
|
46
27
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
if custom_data.nil?
|
51
|
-
is_targeted = (@operator == Operator::UNDEFINED.to_s)
|
52
|
-
elsif @operator != Operator::UNDEFINED.to_s
|
53
|
-
raise KameleoonError.new("Undefined operator #{@operator}"), "Undefined operator #{@operator}" if @op.nil?
|
28
|
+
def op_equal(values, value)
|
29
|
+
values.any? { |v| v.to_f == value.to_f }
|
30
|
+
end
|
54
31
|
|
55
|
-
|
32
|
+
def op_greater(values, value)
|
33
|
+
values.any? { |v| v.to_f > value.to_f }
|
56
34
|
end
|
57
|
-
is_targeted
|
58
|
-
end
|
59
35
|
|
60
|
-
|
36
|
+
def op_lower(values, value)
|
37
|
+
values.any? { |v| v.to_f < value.to_f }
|
38
|
+
end
|
61
39
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
40
|
+
def op_is_true(values, _value)
|
41
|
+
values.any? { |v| v.to_s == 'true' }
|
42
|
+
end
|
66
43
|
|
67
|
-
|
68
|
-
|
69
|
-
|
44
|
+
def op_is_false(values, _value)
|
45
|
+
values.any? { |v| v.to_s == 'false' }
|
46
|
+
end
|
70
47
|
|
71
|
-
|
72
|
-
|
48
|
+
def op_among_values(values, value)
|
49
|
+
all_matches = JSON.parse(value.to_s).map(&:to_s).to_set
|
50
|
+
values.any? { |v| all_matches.include?(v) }
|
51
|
+
end
|
73
52
|
end
|
74
53
|
|
75
|
-
|
76
|
-
|
77
|
-
|
54
|
+
@@op = {
|
55
|
+
Operator::REGULAR_EXPRESSION => method(:op_match),
|
56
|
+
Operator::CONTAINS => method(:op_contains),
|
57
|
+
Operator::EXACT => method(:op_exact),
|
58
|
+
Operator::EQUAL => method(:op_equal),
|
59
|
+
Operator::GREATER => method(:op_greater),
|
60
|
+
Operator::LOWER => method(:op_lower),
|
61
|
+
Operator::IS_TRUE => method(:op_is_true),
|
62
|
+
Operator::IS_FALSE => method(:op_is_false),
|
63
|
+
Operator::AMONG_VALUES => method(:op_among_values)
|
64
|
+
}
|
78
65
|
|
79
|
-
def
|
80
|
-
|
81
|
-
end
|
66
|
+
def initialize(json_condition)
|
67
|
+
super(json_condition)
|
82
68
|
|
83
|
-
|
84
|
-
|
85
|
-
|
69
|
+
if json_condition['valueMatchType'].nil?
|
70
|
+
raise Exception::NotFound.new('valueMatchType'), 'valueMatchType missed'
|
71
|
+
end
|
86
72
|
|
87
|
-
|
88
|
-
|
73
|
+
@type = ConditionType::CUSTOM_DATUM
|
74
|
+
@index = json_condition['customDataIndex']
|
75
|
+
@operator = json_condition['valueMatchType']
|
76
|
+
@value = json_condition['value']
|
89
77
|
end
|
90
78
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
79
|
+
def check(list_data)
|
80
|
+
is_targeted = false
|
81
|
+
custom_data = list_data.select { |data| data.instance == DataType::CUSTOM && data.id == @index }.last
|
82
|
+
if custom_data.nil?
|
83
|
+
is_targeted = (@operator == Operator::UNDEFINED.to_s)
|
84
|
+
elsif @operator != Operator::UNDEFINED.to_s
|
85
|
+
@operation = @@op[@operator]
|
86
|
+
unless @operation
|
87
|
+
raise KameleoonError.new("Undefined operator #{@operator}"), "Undefined operator #{@operator}"
|
88
|
+
end
|
94
89
|
|
95
|
-
|
96
|
-
|
97
|
-
|
90
|
+
is_targeted = @operation.call(custom_data.values, @value)
|
91
|
+
end
|
92
|
+
is_targeted
|
98
93
|
end
|
99
94
|
end
|
100
95
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kameleoon/data/data'
|
4
|
+
|
5
|
+
module Kameleoon
|
6
|
+
# @api private
|
7
|
+
module Targeting
|
8
|
+
# DeviceCondition is a condition for checking device type
|
9
|
+
class DeviceCondition < Condition
|
10
|
+
def initialize(json_condition)
|
11
|
+
super(json_condition)
|
12
|
+
@device_type = json_condition['device']
|
13
|
+
end
|
14
|
+
|
15
|
+
def check(list_data)
|
16
|
+
device = get_last_targeting_data(list_data, Kameleoon::DataType::DEVICE)
|
17
|
+
device && @device_type == device.device_type
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,24 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'kameleoon/targeting/condition'
|
4
|
-
require 'kameleoon/exceptions'
|
5
4
|
|
6
5
|
module Kameleoon
|
7
6
|
# @api private
|
8
7
|
module Targeting
|
9
8
|
# ExclusiveExperiment represents an instance of Exclusive Experiment condition in user account
|
10
9
|
class ExclusiveExperiment < Condition
|
11
|
-
include Kameleoon::Exception
|
12
|
-
|
13
|
-
def initialize(json_condition)
|
14
|
-
if json_condition['targetingType'].nil?
|
15
|
-
raise Exception::NotFound.new('targetingType'), 'targetingType missed'
|
16
|
-
end
|
17
|
-
|
18
|
-
@type = json_condition['targetingType']
|
19
|
-
@include = true
|
20
|
-
end
|
21
|
-
|
22
10
|
def check(data)
|
23
11
|
experiment_id = data.experiment_id
|
24
12
|
storage = data.storage
|
@@ -0,0 +1,21 @@
|
|
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
|
+
# PageTitleCondition is a condition for checking title of a page
|
10
|
+
class PageTitleCondition < StringValueCondition
|
11
|
+
def initialize(json_condition)
|
12
|
+
super(json_condition, json_condition['title'])
|
13
|
+
end
|
14
|
+
|
15
|
+
def check(list_data)
|
16
|
+
page_view = get_last_targeting_data(list_data, Kameleoon::DataType::PAGE_VIEW)
|
17
|
+
page_view && check_targeting(page_view.title)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
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
|
+
# PageUrlCondition is a condition for checking url of a page
|
10
|
+
class PageUrlCondition < StringValueCondition
|
11
|
+
def initialize(json_condition)
|
12
|
+
super(json_condition, json_condition['url'])
|
13
|
+
end
|
14
|
+
|
15
|
+
def check(list_data)
|
16
|
+
page_view = get_last_targeting_data(list_data, Kameleoon::DataType::PAGE_VIEW)
|
17
|
+
page_view && check_targeting(page_view.url)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|