splitclient-rb 4.3.0.canary.2 → 4.3.0
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/CHANGES.txt +2 -1
- data/Detailed-README.md +8 -0
- data/lib/splitclient-rb.rb +0 -1
- data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +8 -10
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +27 -22
- data/lib/splitclient-rb/engine/matchers/combiners.rb +3 -7
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +33 -44
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +9 -5
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +9 -5
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +16 -4
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +9 -5
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +12 -4
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +12 -4
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +26 -21
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +9 -5
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +25 -21
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +25 -21
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +12 -4
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +19 -13
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +9 -5
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +5 -1
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +12 -4
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +8 -7
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +25 -20
- data/lib/splitclient-rb/engine/parser/condition.rb +1 -1
- data/lib/splitclient-rb/engine/parser/evaluator.rb +14 -16
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +4 -5
- data/lib/splitclient-rb/engine/matchers/attribute_matcher.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b62b60ce935de1b5345ec16107e6911321abf9c
|
4
|
+
data.tar.gz: 2ed5525256582608b165f9a42a056657fb6fc24c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 837b99afc42609f08b51eee920c0b9492da45fb93e3ddfe187f0edc454e36077684e1bef54312a3a31e529d7fba2b10730179cc7e82a88becc4dc4e9d2435acf
|
7
|
+
data.tar.gz: cb785d0b3152892b86fa24a7b3369247ee4d17ffd2a4e9d01452bdb3d4e7b7eedb7648793ce8eb5c9e51d3ce2911256ce1da5e9bea7ad285d90f1a6bee913708
|
data/CHANGES.txt
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
4.3.0 (
|
1
|
+
4.3.0 (Oct 13th, 2017)
|
2
2
|
- Add impression listener
|
3
3
|
- Add support for client shutdown (destroy())
|
4
4
|
- Add "time" to the routed impressions
|
5
5
|
- Add support to apply attribute matcher to the traffic type
|
6
|
+
- Add support for string matchers to match on matching keys
|
6
7
|
|
7
8
|
4.2.3 (August 4, 2017)
|
8
9
|
- Use ENV vars in producer
|
data/Detailed-README.md
CHANGED
@@ -480,6 +480,14 @@ end
|
|
480
480
|
|
481
481
|
By doing that SDK will recreate threads for each new worker, besides master.
|
482
482
|
|
483
|
+
## Proxy support
|
484
|
+
|
485
|
+
SDK respects http_proxy environment variable, all you need to do to use proxy is assign your proxy address to that variable in the format:
|
486
|
+
|
487
|
+
```
|
488
|
+
http_proxy=http://username:password@hostname:port
|
489
|
+
```
|
490
|
+
|
483
491
|
## Framework support
|
484
492
|
|
485
493
|
Currently SDK supports:
|
data/lib/splitclient-rb.rb
CHANGED
@@ -43,7 +43,6 @@ require 'splitclient-rb/engine/parser/condition'
|
|
43
43
|
require 'splitclient-rb/engine/parser/partition'
|
44
44
|
require 'splitclient-rb/engine/parser/split_adapter'
|
45
45
|
require 'splitclient-rb/engine/parser/evaluator'
|
46
|
-
require 'splitclient-rb/engine/matchers/attribute_matcher'
|
47
46
|
require 'splitclient-rb/engine/matchers/combiners'
|
48
47
|
require 'splitclient-rb/engine/matchers/combining_matcher'
|
49
48
|
require 'splitclient-rb/engine/matchers/all_keys_matcher'
|
@@ -2,20 +2,14 @@ module SplitIoClient
|
|
2
2
|
#
|
3
3
|
# class to implement the all keys matcher
|
4
4
|
#
|
5
|
-
class AllKeysMatcher
|
6
|
-
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@matcher_type = 'ALL_KEYS'
|
10
|
-
end
|
5
|
+
class AllKeysMatcher
|
6
|
+
MATCHER_TYPE = 'ALL_KEYS'.freeze
|
11
7
|
|
12
8
|
#
|
13
9
|
# evaluates if the key matches the matcher
|
14
10
|
#
|
15
|
-
# @param key [string] key value to be matched
|
16
|
-
#
|
17
11
|
# @return [boolean] true for all instances
|
18
|
-
def match?(
|
12
|
+
def match?(_args)
|
19
13
|
true
|
20
14
|
end
|
21
15
|
|
@@ -24,7 +18,7 @@ module SplitIoClient
|
|
24
18
|
#
|
25
19
|
# @param obj [object] object to be evaluated
|
26
20
|
#
|
27
|
-
# @
|
21
|
+
# @return [boolean] true if obj equals the matcher
|
28
22
|
def equals?(obj)
|
29
23
|
if obj.nil?
|
30
24
|
false
|
@@ -37,6 +31,10 @@ module SplitIoClient
|
|
37
31
|
end
|
38
32
|
end
|
39
33
|
|
34
|
+
def string_type?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
40
38
|
#
|
41
39
|
# function to print string value for this matcher
|
42
40
|
#
|
@@ -1,25 +1,25 @@
|
|
1
1
|
module SplitIoClient
|
2
|
+
class BetweenMatcher
|
3
|
+
MATCHER_TYPE = 'BETWEEN'.freeze
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :matcher_type
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute_hash)
|
8
|
-
@matcher_type = "BETWEEN"
|
9
8
|
@attribute = attribute_hash[:attribute]
|
10
9
|
@data_type = attribute_hash[:data_type]
|
11
|
-
@start_value =
|
12
|
-
@end_value =
|
10
|
+
@start_value = formatted_value(attribute_hash[:start_value], true)
|
11
|
+
@end_value = formatted_value(attribute_hash[:end_value], true)
|
13
12
|
end
|
14
13
|
|
15
|
-
def match?(
|
16
|
-
|
17
|
-
if
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def match?(args)
|
15
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
16
|
+
return false if args.key?(:value) && args[:value].nil?
|
17
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
18
|
+
|
19
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
20
|
+
return false unless value.is_a?(Integer)
|
21
21
|
|
22
|
-
|
22
|
+
(@start_value..@end_value).include? value
|
23
23
|
end
|
24
24
|
|
25
25
|
def equals?(obj)
|
@@ -34,18 +34,23 @@ module SplitIoClient
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
def string_type?
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
37
41
|
private
|
38
|
-
|
42
|
+
|
43
|
+
def formatted_value(value, sdk_data = false)
|
39
44
|
case @data_type
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
when 'NUMBER'
|
46
|
+
value
|
47
|
+
when 'DATETIME'
|
48
|
+
value = value / 1000 if sdk_data
|
49
|
+
|
50
|
+
SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
|
51
|
+
else
|
52
|
+
@logger.error('Invalid data type')
|
47
53
|
end
|
48
54
|
end
|
49
55
|
end
|
50
|
-
|
51
56
|
end
|
@@ -2,63 +2,59 @@ module SplitIoClient
|
|
2
2
|
#
|
3
3
|
# class to implement the combining matcher
|
4
4
|
#
|
5
|
-
class CombiningMatcher
|
5
|
+
class CombiningMatcher
|
6
|
+
MATCHER_TYPE = 'COMBINING_MATCHER'.freeze
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@matcher_list = []
|
11
|
-
|
12
|
-
#
|
13
|
-
# combiner value
|
14
|
-
#
|
15
|
-
@combiner = ''
|
16
|
-
|
17
|
-
def initialize(combiner, delegates)
|
18
|
-
unless delegates.nil?
|
19
|
-
@matcher_list = delegates
|
20
|
-
end
|
21
|
-
unless combiner.nil?
|
22
|
-
@combiner = combiner
|
23
|
-
end
|
8
|
+
def initialize(combiner = '', matchers = [])
|
9
|
+
@combiner = combiner
|
10
|
+
@matchers = matchers
|
24
11
|
end
|
25
12
|
|
26
13
|
#
|
27
14
|
# evaluates if the key matches the matchers within the combiner
|
28
15
|
#
|
29
|
-
# @param
|
16
|
+
# @param matching_key [string] key value to be matched
|
17
|
+
# @param bucketing_key [string] bucketing key to be matched
|
18
|
+
# @param evaluator [instance of Evaluator class]
|
19
|
+
# @param attributes [hash]
|
30
20
|
#
|
31
|
-
# @return [boolean]
|
32
|
-
def match?(
|
33
|
-
if @
|
34
|
-
return false
|
35
|
-
end
|
21
|
+
# @return [boolean]
|
22
|
+
def match?(args)
|
23
|
+
return false if @matchers.empty?
|
36
24
|
|
37
25
|
case @combiner
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
return false
|
26
|
+
when Combiners::AND
|
27
|
+
return eval_and(args)
|
28
|
+
else
|
29
|
+
@logger.error('Invalid combiner type')
|
43
30
|
end
|
31
|
+
|
32
|
+
false
|
44
33
|
end
|
45
34
|
|
46
35
|
#
|
47
36
|
# auxiliary method to evaluate each of the matchers within the combiner
|
48
37
|
#
|
49
|
-
# @param
|
38
|
+
# @param matching_key [string] key value to be matched
|
39
|
+
# @param bucketing_key [string] bucketing key to be matched
|
50
40
|
# @param evaluator [Evaluator] used in dependency_matcher
|
51
41
|
# @param attributes [hash] attributes to pass to the treatment class
|
52
42
|
#
|
53
43
|
# @return [boolean] match value for combiner delegates
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
44
|
+
def eval_and(args)
|
45
|
+
# Convert all keys to symbols
|
46
|
+
args[:attributes] = args[:attributes].inject({}){ |memo, (k,v)| memo[k.to_sym] = v; memo } if args && args[:attributes]
|
47
|
+
@matchers.all? do |matcher|
|
48
|
+
if match_with_key?(matcher)
|
49
|
+
matcher.match?(value: args[:matching_key])
|
50
|
+
else
|
51
|
+
matcher.match?(args)
|
52
|
+
end
|
59
53
|
end
|
54
|
+
end
|
60
55
|
|
61
|
-
|
56
|
+
def match_with_key?(matcher)
|
57
|
+
matcher.respond_to?(:attribute) && matcher.attribute.nil? && matcher.string_type?
|
62
58
|
end
|
63
59
|
|
64
60
|
#
|
@@ -84,14 +80,7 @@ module SplitIoClient
|
|
84
80
|
#
|
85
81
|
# @reutrn [string] string value of this matcher
|
86
82
|
def to_s
|
87
|
-
|
88
|
-
@matcher_list.each_with_index do |matcher, i|
|
89
|
-
result += matcher.to_s
|
90
|
-
result += ' ' + @combiner if i != 0
|
91
|
-
end
|
92
|
-
result
|
83
|
+
@matcher_list.map(&:to_s).join("#{@combiner} ")
|
93
84
|
end
|
94
|
-
|
95
85
|
end
|
96
|
-
|
97
86
|
end
|
@@ -1,17 +1,21 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class ContainsAllMatcher < SetMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'CONTAINS_ALL'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, remote_array)
|
8
8
|
super(attribute, remote_array)
|
9
9
|
end
|
10
10
|
|
11
|
-
def match?(
|
11
|
+
def match?(args)
|
12
12
|
return false if @remote_set.empty?
|
13
13
|
|
14
|
-
@remote_set.subset? local_set(
|
14
|
+
@remote_set.subset? local_set(args[:attributes], @attribute)
|
15
|
+
end
|
16
|
+
|
17
|
+
def string_type?
|
18
|
+
false
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class ContainsAnyMatcher < SetMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'CONTAINS_ANY'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, remote_array)
|
8
8
|
super(attribute, remote_array)
|
9
9
|
end
|
10
10
|
|
11
|
-
def match?(
|
12
|
-
local_set(
|
11
|
+
def match?(args)
|
12
|
+
local_set(args[:attributes], @attribute).intersect? @remote_set
|
13
|
+
end
|
14
|
+
|
15
|
+
def string_type?
|
16
|
+
false
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -1,18 +1,30 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class ContainsMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'CONTAINS_WITH'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, substr_list)
|
8
8
|
@attribute = attribute
|
9
9
|
@substr_list = substr_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(args)
|
13
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
14
|
+
return false if args.key?(:value) && args[:value].nil?
|
15
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
16
|
+
|
17
|
+
value = args[:value] || args[:attributes].fetch(@attribute) do |a|
|
18
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
19
|
+
end
|
20
|
+
|
13
21
|
return false if @substr_list.empty?
|
14
22
|
|
15
23
|
@substr_list.any? { |substr| value.to_s.include? substr }
|
16
24
|
end
|
25
|
+
|
26
|
+
def string_type?
|
27
|
+
true
|
28
|
+
end
|
17
29
|
end
|
18
30
|
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class DependencyMatcher
|
3
|
-
|
4
|
-
'IN_SPLIT_TREATMENT'.freeze
|
5
|
-
end
|
3
|
+
MATCHER_TYPE = 'IN_SPLIT_TREATMENT'.freeze
|
6
4
|
|
7
5
|
def initialize(split, treatments)
|
8
6
|
@split = split
|
9
7
|
@treatments = treatments
|
10
8
|
end
|
11
9
|
|
12
|
-
def match?(
|
13
|
-
|
10
|
+
def match?(args)
|
11
|
+
keys = { matching_key: args[:matching_key], bucketing_key: args[:bucketing_key] }
|
12
|
+
|
13
|
+
@treatments.include?(args[:evaluator].call(keys, @split, args[:attributes])[:treatment])
|
14
|
+
end
|
15
|
+
|
16
|
+
def string_type?
|
17
|
+
false
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -1,18 +1,26 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class EndsWithMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'ENDS_WITH'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, suffix_list)
|
8
8
|
@attribute = attribute
|
9
9
|
@suffix_list = suffix_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(args)
|
13
|
+
value = args[:value] || args[:attributes].fetch(@attribute) do |a|
|
14
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
+
end
|
16
|
+
|
13
17
|
return false if @suffix_list.empty?
|
14
18
|
|
15
19
|
@suffix_list.any? { |suffix| value.to_s.end_with? suffix }
|
16
20
|
end
|
21
|
+
|
22
|
+
def string_type?
|
23
|
+
true
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
@@ -1,19 +1,27 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class EqualToBooleanMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'EQUAL_TO_BOOLEAN'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, boolean)
|
8
8
|
@attribute = attribute
|
9
9
|
@boolean = boolean
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(args)
|
13
|
+
value = args[:attributes].fetch(@attribute) do |a|
|
14
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
+
end
|
16
|
+
|
13
17
|
value = false if value.to_s.downcase == 'false'
|
14
18
|
value = true if value.to_s.downcase == 'true'
|
15
19
|
|
16
20
|
value == @boolean
|
17
21
|
end
|
22
|
+
|
23
|
+
def string_type?
|
24
|
+
false
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
@@ -1,22 +1,23 @@
|
|
1
1
|
module SplitIoClient
|
2
|
+
class EqualToMatcher
|
3
|
+
MATCHER_TYPE = 'EQUAL_TO'.freeze
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :matcher_type
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute_hash)
|
8
|
-
@matcher_type = "EQUAL_TO"
|
9
8
|
@attribute = attribute_hash[:attribute]
|
10
9
|
@data_type = attribute_hash[:data_type]
|
11
|
-
@value =
|
10
|
+
@value = formatted_value(attribute_hash[:value], true)
|
12
11
|
end
|
13
12
|
|
14
|
-
def match?(
|
15
|
-
|
16
|
-
if
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
def match?(args)
|
14
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
15
|
+
return false if args.key?(:value) && args[:value].nil?
|
16
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
17
|
+
|
18
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
19
|
+
|
20
|
+
value.is_a?(Integer) ? (value == @value) : false
|
20
21
|
end
|
21
22
|
|
22
23
|
def equals?(obj)
|
@@ -31,19 +32,23 @@ module SplitIoClient
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
def string_type?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
34
39
|
private
|
35
|
-
|
40
|
+
|
41
|
+
def formatted_value(value, sdk_data = false)
|
36
42
|
case @data_type
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
when 'NUMBER'
|
44
|
+
value
|
45
|
+
when 'DATETIME'
|
46
|
+
value = value / 1000 if sdk_data
|
47
|
+
|
48
|
+
SplitIoClient::Utilities.to_milis_zero_out_from_hour value
|
49
|
+
else
|
50
|
+
@logger.error('Invalid data type')
|
44
51
|
end
|
45
52
|
end
|
46
|
-
|
47
53
|
end
|
48
|
-
|
49
54
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class EqualToSetMatcher < SetMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'EQUAL_TO_SET'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, remote_array)
|
8
8
|
super(attribute, remote_array)
|
9
9
|
end
|
10
10
|
|
11
|
-
def match?(
|
12
|
-
local_set(
|
11
|
+
def match?(args)
|
12
|
+
local_set(args[:attributes], @attribute) == @remote_set
|
13
|
+
end
|
14
|
+
|
15
|
+
def string_type?
|
16
|
+
false
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -1,22 +1,23 @@
|
|
1
1
|
module SplitIoClient
|
2
|
+
class GreaterThanOrEqualToMatcher
|
3
|
+
MATCHER_TYPE = 'GREATER_THAN_OR_EQUAL_TO'.freeze
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :matcher_type
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute_hash)
|
8
|
-
@matcher_type = "GREATER_THAN_OR_EQUAL_TO"
|
9
8
|
@attribute = attribute_hash[:attribute]
|
10
9
|
@data_type = attribute_hash[:data_type]
|
11
|
-
@value =
|
10
|
+
@value = formatted_value(attribute_hash[:value], true)
|
12
11
|
end
|
13
12
|
|
14
|
-
def match?(
|
15
|
-
|
16
|
-
if
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
def match?(args)
|
14
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
15
|
+
return false if args.key?(:value) && args[:value].nil?
|
16
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
17
|
+
|
18
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
19
|
+
|
20
|
+
value.is_a?(Integer) ? (value >= @value) : false
|
20
21
|
end
|
21
22
|
|
22
23
|
def equals?(obj)
|
@@ -31,19 +32,22 @@ module SplitIoClient
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
def string_type?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
34
39
|
private
|
35
|
-
|
40
|
+
|
41
|
+
def formatted_value(value, sdk_data = false)
|
36
42
|
case @data_type
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
when 'NUMBER'
|
44
|
+
return value
|
45
|
+
when 'DATETIME'
|
46
|
+
value = value / 1000 if sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_our
|
47
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
|
48
|
+
else
|
49
|
+
@logger.error('Invalid data type')
|
44
50
|
end
|
45
51
|
end
|
46
|
-
|
47
52
|
end
|
48
|
-
|
49
53
|
end
|
@@ -1,22 +1,23 @@
|
|
1
1
|
module SplitIoClient
|
2
|
+
class LessThanOrEqualToMatcher
|
3
|
+
MATCHER_TYPE = 'LESS_THAN_OR_EQUAL_TO'.freeze
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :matcher_type
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute_hash)
|
8
|
-
@matcher_type = "LESS_THAN_OR_EQUAL_TO"
|
9
8
|
@attribute = attribute_hash[:attribute]
|
10
9
|
@data_type = attribute_hash[:data_type]
|
11
|
-
@value =
|
10
|
+
@value = formatted_value(attribute_hash[:value], true)
|
12
11
|
end
|
13
12
|
|
14
|
-
def match?(
|
15
|
-
|
16
|
-
if
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
def match?(args)
|
14
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
15
|
+
return false if args.key?(:value) && args[:value].nil?
|
16
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
17
|
+
|
18
|
+
value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
|
19
|
+
|
20
|
+
value.is_a?(Integer) ? (value <= @value) : false
|
20
21
|
end
|
21
22
|
|
22
23
|
def equals?(obj)
|
@@ -31,19 +32,22 @@ module SplitIoClient
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
def string_type?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
34
39
|
private
|
35
|
-
|
40
|
+
|
41
|
+
def formatted_value(value, sdk_data = false)
|
36
42
|
case @data_type
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
when 'NUMBER'
|
44
|
+
return value
|
45
|
+
when 'DATETIME'
|
46
|
+
value = value / 1000 if sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_our
|
47
|
+
return SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
|
48
|
+
else
|
49
|
+
@logger.error('Invalid data type')
|
44
50
|
end
|
45
51
|
end
|
46
|
-
|
47
52
|
end
|
48
|
-
|
49
53
|
end
|
@@ -1,16 +1,24 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class MatchesStringMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'MATCHES_STRING'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, regexp_string)
|
8
8
|
@attribute = attribute
|
9
9
|
@regexp_string = @regexp_string.is_a?(Regexp) ? regexp_string : Regexp.new(regexp_string)
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(args)
|
13
|
+
value = args[:value] || args[:attributes].fetch(@attribute) do |a|
|
14
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
+
end
|
16
|
+
|
13
17
|
(value =~ @regexp_string) != nil
|
14
18
|
end
|
19
|
+
|
20
|
+
def string_type?
|
21
|
+
true
|
22
|
+
end
|
15
23
|
end
|
16
24
|
end
|
@@ -1,16 +1,12 @@
|
|
1
1
|
module SplitIoClient
|
2
|
-
|
3
2
|
#
|
4
3
|
# class to implement the negation of a matcher
|
5
4
|
#
|
6
|
-
class NegationMatcher
|
7
|
-
|
8
|
-
@matcher = nil
|
5
|
+
class NegationMatcher
|
6
|
+
MATCHER_TYPE = 'NEGATION_MATCHER'.freeze
|
9
7
|
|
10
|
-
def initialize(matcher)
|
11
|
-
|
12
|
-
@matcher = matcher
|
13
|
-
end
|
8
|
+
def initialize(matcher = nil)
|
9
|
+
@matcher = matcher
|
14
10
|
end
|
15
11
|
|
16
12
|
#
|
@@ -19,8 +15,20 @@ module SplitIoClient
|
|
19
15
|
# @param key [string] key value to be matched
|
20
16
|
#
|
21
17
|
# @return [boolean] evaluation of the negation matcher
|
22
|
-
def match?(
|
23
|
-
!@matcher.match?(
|
18
|
+
def match?(args)
|
19
|
+
!@matcher.match?(args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to?(method)
|
23
|
+
@matcher.respond_to? method
|
24
|
+
end
|
25
|
+
|
26
|
+
def attribute
|
27
|
+
@matcher.attribute
|
28
|
+
end
|
29
|
+
|
30
|
+
def string_type?
|
31
|
+
@matcher.string_type?
|
24
32
|
end
|
25
33
|
|
26
34
|
#
|
@@ -46,9 +54,7 @@ module SplitIoClient
|
|
46
54
|
#
|
47
55
|
# @reutrn [string] string value of this matcher
|
48
56
|
def to_s
|
49
|
-
|
57
|
+
"not #{@matcher}"
|
50
58
|
end
|
51
|
-
|
52
59
|
end
|
53
|
-
|
54
60
|
end
|
@@ -1,19 +1,23 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class PartOfSetMatcher < SetMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'PART_OF_SET'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, remote_array)
|
8
8
|
super(attribute, remote_array)
|
9
9
|
end
|
10
10
|
|
11
|
-
def match?(
|
12
|
-
@local_set = local_set(
|
11
|
+
def match?(args)
|
12
|
+
@local_set = local_set(args[:attributes], @attribute)
|
13
13
|
|
14
14
|
return false if @local_set.empty?
|
15
15
|
|
16
16
|
@local_set.subset? @remote_set
|
17
17
|
end
|
18
|
+
|
19
|
+
def string_type?
|
20
|
+
false
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
@@ -1,12 +1,16 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
class SetMatcher
|
3
5
|
protected
|
4
6
|
|
5
7
|
def initialize(attribute, remote_array)
|
8
|
+
@attribute = attribute
|
6
9
|
@remote_set = remote_array.to_set
|
7
10
|
end
|
8
11
|
|
9
|
-
def local_set(data)
|
12
|
+
def local_set(data, attribute)
|
13
|
+
data = data.fetch(attribute) { |a| data[a.to_s] || data[a.to_sym] }
|
10
14
|
# Allow user to pass individual elements as well
|
11
15
|
local_array = data.kind_of?(Array) ? data : [data]
|
12
16
|
|
@@ -1,18 +1,26 @@
|
|
1
1
|
module SplitIoClient
|
2
2
|
class StartsWithMatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
MATCHER_TYPE = 'STARTS_WITH'.freeze
|
4
|
+
|
5
|
+
attr_reader :attribute
|
6
6
|
|
7
7
|
def initialize(attribute, prefix_list)
|
8
8
|
@attribute = attribute
|
9
9
|
@prefix_list = prefix_list
|
10
10
|
end
|
11
11
|
|
12
|
-
def match?(
|
12
|
+
def match?(args)
|
13
|
+
value = args[:value] || args[:attributes].fetch(@attribute) do |a|
|
14
|
+
args[:attributes][a.to_s] || args[:attributes][a.to_sym]
|
15
|
+
end
|
16
|
+
|
13
17
|
return false if @prefix_list.empty?
|
14
18
|
|
15
19
|
@prefix_list.any? { |prefix| value.to_s.start_with? prefix }
|
16
20
|
end
|
21
|
+
|
22
|
+
def string_type?
|
23
|
+
true
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
@@ -1,14 +1,11 @@
|
|
1
1
|
module SplitIoClient
|
2
|
-
|
3
2
|
#
|
4
3
|
# class to implement the user defined matcher
|
5
4
|
#
|
6
|
-
class UserDefinedSegmentMatcher
|
7
|
-
|
8
|
-
attr_reader :matcher_type
|
5
|
+
class UserDefinedSegmentMatcher
|
6
|
+
MATCHER_TYPE = 'IN_SEGMENT'.freeze
|
9
7
|
|
10
8
|
def initialize(segments_repository, segment_name)
|
11
|
-
@matcher_type = "IN_SEGMENT"
|
12
9
|
@segments_repository = segments_repository
|
13
10
|
@segment_name = segment_name
|
14
11
|
end
|
@@ -19,8 +16,8 @@ module SplitIoClient
|
|
19
16
|
# @param key [string] key value to be matched
|
20
17
|
#
|
21
18
|
# @return [boolean] evaluation of the key against the segment
|
22
|
-
def match?(
|
23
|
-
@segments_repository.in_segment?(@segment_name, matching_key)
|
19
|
+
def match?(args)
|
20
|
+
@segments_repository.in_segment?(@segment_name, args[:value] || args[:matching_key])
|
24
21
|
end
|
25
22
|
|
26
23
|
#
|
@@ -40,5 +37,9 @@ module SplitIoClient
|
|
40
37
|
false
|
41
38
|
end
|
42
39
|
end
|
40
|
+
|
41
|
+
def string_type?
|
42
|
+
false
|
43
|
+
end
|
43
44
|
end
|
44
45
|
end
|
@@ -1,33 +1,36 @@
|
|
1
1
|
module SplitIoClient
|
2
|
-
|
3
2
|
#
|
4
3
|
# class to implement the user defined matcher
|
5
4
|
#
|
6
5
|
class WhitelistMatcher < NoMethodError
|
6
|
+
MATCHER_TYPE = 'WHITELIST_MATCHER'
|
7
7
|
|
8
|
-
attr_reader :
|
9
|
-
|
10
|
-
# variable that contains the keys of the whitelist
|
11
|
-
@whitelist = []
|
8
|
+
attr_reader :attribute
|
12
9
|
|
13
10
|
def initialize(whitelist_data)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
@whitelist = case whitelist_data
|
12
|
+
when Array
|
13
|
+
whitelist_data
|
14
|
+
when Hash
|
15
|
+
@matcher_type = 'ATTR_WHITELIST'
|
18
16
|
@attribute = whitelist_data[:attribute]
|
19
|
-
|
17
|
+
|
18
|
+
whitelist_data[:value]
|
19
|
+
else
|
20
|
+
[]
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
def match?(
|
24
|
-
|
25
|
-
|
26
|
-
if !
|
27
|
-
|
28
|
-
|
24
|
+
def match?(args)
|
25
|
+
return @whitelist.include?(args[:value] || args[:matching_key]) unless @matcher_type == 'ATTR_WHITELIST'
|
26
|
+
|
27
|
+
return false if !args.key?(:attributes) && !args.key?(:value)
|
28
|
+
return false if args.key?(:value) && args[:value].nil?
|
29
|
+
return false if args.key?(:attributes) && args[:attributes].nil?
|
29
30
|
|
30
|
-
|
31
|
+
return @whitelist.include?(args[:value] || args[:attributes][@attribute.to_sym])
|
32
|
+
|
33
|
+
false
|
31
34
|
end
|
32
35
|
|
33
36
|
#
|
@@ -48,14 +51,16 @@ module SplitIoClient
|
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
54
|
+
def string_type?
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
51
58
|
#
|
52
59
|
# function to print string value for this matcher
|
53
60
|
#
|
54
61
|
# @reutrn [string] string value of this matcher
|
55
62
|
def to_s
|
56
|
-
|
63
|
+
"in segment #{@whitelist}"
|
57
64
|
end
|
58
|
-
|
59
65
|
end
|
60
|
-
|
61
66
|
end
|
@@ -58,23 +58,21 @@ module SplitIoClient
|
|
58
58
|
in_rollout = true
|
59
59
|
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
matcher = SplitIoClient::AttributeMatcher.new(nil, matcher_type(condition))
|
68
|
-
end
|
69
|
-
if matcher.match?(keys[:matching_key], keys[:bucketing_key], self, attributes)
|
70
|
-
key = keys[:bucketing_key] ? keys[:bucketing_key] : keys[:matching_key]
|
71
|
-
result = Splitter.get_treatment(key, split[:seed], condition.partitions, split[:algo])
|
61
|
+
condition_matched = matcher_type(condition).match?(
|
62
|
+
matching_key: keys[:matching_key],
|
63
|
+
bucketing_key: keys[:bucketing_key],
|
64
|
+
evaluator: self,
|
65
|
+
attributes: attributes
|
66
|
+
)
|
72
67
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
68
|
+
next unless condition_matched
|
69
|
+
|
70
|
+
result = Splitter.get_treatment(key, split[:seed], condition.partitions, split[:algo])
|
71
|
+
|
72
|
+
if result.nil?
|
73
|
+
return treatment_hash(Models::Label::NO_RULE_MATCHED, split[:defaultTreatment], split[:changeNumber])
|
74
|
+
else
|
75
|
+
return treatment_hash(c[:label], result, split[:changeNumber])
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: splitclient-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.0
|
4
|
+
version: 4.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -283,7 +283,6 @@ files:
|
|
283
283
|
- lib/splitclient-rb/engine/api/splits.rb
|
284
284
|
- lib/splitclient-rb/engine/evaluator/splitter.rb
|
285
285
|
- lib/splitclient-rb/engine/matchers/all_keys_matcher.rb
|
286
|
-
- lib/splitclient-rb/engine/matchers/attribute_matcher.rb
|
287
286
|
- lib/splitclient-rb/engine/matchers/between_matcher.rb
|
288
287
|
- lib/splitclient-rb/engine/matchers/combiners.rb
|
289
288
|
- lib/splitclient-rb/engine/matchers/combining_matcher.rb
|
@@ -346,9 +345,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
346
345
|
version: '0'
|
347
346
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
348
347
|
requirements:
|
349
|
-
- - "
|
348
|
+
- - ">="
|
350
349
|
- !ruby/object:Gem::Version
|
351
|
-
version:
|
350
|
+
version: '0'
|
352
351
|
requirements: []
|
353
352
|
rubyforge_project:
|
354
353
|
rubygems_version: 2.5.2
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module SplitIoClient
|
2
|
-
class AttributeMatcher
|
3
|
-
def initialize(attribute, matcher)
|
4
|
-
@attribute = attribute
|
5
|
-
@matcher = matcher
|
6
|
-
end
|
7
|
-
|
8
|
-
def match?(matching_key, bucketing_key = nil, evaluator = nil, attributes = {})
|
9
|
-
if @attribute != nil
|
10
|
-
return false unless attributes
|
11
|
-
|
12
|
-
value = attributes.fetch(@attribute) { |name| attributes[name.to_s] || attributes[name.to_sym] }
|
13
|
-
|
14
|
-
@matcher.match?(value, bucketing_key, nil, nil)
|
15
|
-
else
|
16
|
-
@matcher.match?(matching_key, bucketing_key, evaluator, attributes)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|