splitclient-rb 6.0.1 → 6.1.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -1
  3. data/.simplecov +1 -0
  4. data/README.md +2 -2
  5. data/lib/splitclient-rb.rb +1 -0
  6. data/lib/splitclient-rb/clients/split_client.rb +30 -9
  7. data/lib/splitclient-rb/engine/api/client.rb +8 -9
  8. data/lib/splitclient-rb/engine/api/events.rb +4 -2
  9. data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +10 -8
  10. data/lib/splitclient-rb/engine/api/impressions.rb +4 -2
  11. data/lib/splitclient-rb/engine/api/metrics.rb +5 -5
  12. data/lib/splitclient-rb/engine/api/segments.rb +5 -1
  13. data/lib/splitclient-rb/engine/api/splits.rb +4 -4
  14. data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +8 -13
  15. data/lib/splitclient-rb/engine/matchers/between_matcher.rb +12 -23
  16. data/lib/splitclient-rb/engine/matchers/combiners.rb +3 -1
  17. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +16 -24
  18. data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +10 -7
  19. data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +7 -6
  20. data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +19 -8
  21. data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +8 -3
  22. data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +21 -6
  23. data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +17 -8
  24. data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +11 -23
  25. data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +7 -6
  26. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +13 -25
  27. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +13 -25
  28. data/lib/splitclient-rb/engine/matchers/matcher.rb +30 -0
  29. data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +6 -2
  30. data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +8 -22
  31. data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +10 -7
  32. data/lib/splitclient-rb/engine/matchers/set_matcher.rb +7 -1
  33. data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +18 -5
  34. data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +7 -25
  35. data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +33 -35
  36. data/lib/splitclient-rb/managers/split_manager.rb +10 -3
  37. data/lib/splitclient-rb/split_config.rb +34 -9
  38. data/lib/splitclient-rb/split_factory.rb +27 -0
  39. data/lib/splitclient-rb/validators.rb +104 -36
  40. data/lib/splitclient-rb/version.rb +1 -1
  41. metadata +6 -4
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  #
3
5
  # class to represent combiner values
4
6
  #
5
7
  class Combiners
6
8
  # available combiners of the sdk
7
- AND = 'AND'.freeze
9
+ AND = 'AND'
8
10
  end
9
11
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  #
3
5
  # class to implement the combining matcher
4
6
  #
5
- class CombiningMatcher
6
- MATCHER_TYPE = 'COMBINING_MATCHER'.freeze
7
+ class CombiningMatcher < Matcher
8
+ MATCHER_TYPE = 'COMBINING_MATCHER'
7
9
 
8
10
  def initialize(combiner = '', matchers = [])
9
11
  @combiner = combiner
@@ -20,12 +22,18 @@ module SplitIoClient
20
22
  #
21
23
  # @return [boolean]
22
24
  def match?(args)
23
- return false if @matchers.empty?
25
+ if @matchers.empty?
26
+ SplitLogger.log_if_debug('[CombiningMatcher] Matchers Empty')
27
+ return false
28
+ end
24
29
 
25
30
  case @combiner
26
31
  when Combiners::AND
27
- return eval_and(args)
32
+ matches = eval_and(args)
33
+ SplitLogger.log_if_debug("[CombiningMatcher] Combiner AND result -> #{matches}")
34
+ return matches
28
35
  else
36
+ SplitLogger.log_if_debug("[CombiningMatcher] Invalid Combiner Type - Combiner -> #{@combiner}")
29
37
  @logger.error('Invalid combiner type')
30
38
  end
31
39
 
@@ -43,7 +51,9 @@ module SplitIoClient
43
51
  # @return [boolean] match value for combiner delegates
44
52
  def eval_and(args)
45
53
  # Convert all keys to symbols
46
- args[:attributes] = args[:attributes].inject({}){ |memo, (k,v)| memo[k.to_sym] = v; memo } if args && args[:attributes]
54
+ if args && args[:attributes]
55
+ args[:attributes] = args[:attributes].each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
56
+ end
47
57
  @matchers.all? do |matcher|
48
58
  if match_with_key?(matcher)
49
59
  matcher.match?(value: args[:matching_key])
@@ -57,28 +67,10 @@ module SplitIoClient
57
67
  matcher.respond_to?(:attribute) && matcher.attribute.nil? && matcher.string_type?
58
68
  end
59
69
 
60
- #
61
- # evaluates if the given object equals the matcher
62
- #
63
- # @param obj [object] object to be evaluated
64
- #
65
- # @returns [boolean] true if obj equals the matcher
66
- def equals?(obj)
67
- if obj.nil?
68
- false
69
- elsif !obj.instance_of?(CombiningMatcher)
70
- false
71
- elsif self.equal?(obj)
72
- true
73
- else
74
- false
75
- end
76
- end
77
-
78
70
  #
79
71
  # function to print string value for this matcher
80
72
  #
81
- # @reutrn [string] string value of this matcher
73
+ # @return [string] string value of this matcher
82
74
  def to_s
83
75
  @matcher_list.map(&:to_s).join("#{@combiner} ")
84
76
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class ContainsAllMatcher < SetMatcher
3
- MATCHER_TYPE = 'CONTAINS_ALL'.freeze
5
+ MATCHER_TYPE = 'CONTAINS_ALL'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -9,13 +11,14 @@ module SplitIoClient
9
11
  end
10
12
 
11
13
  def match?(args)
12
- return false if @remote_set.empty?
13
-
14
- @remote_set.subset? local_set(args[:attributes], @attribute)
15
- end
14
+ if @remote_set.empty?
15
+ SplitLogger.log_if_debug('[ContainsAllMatcher] Remote Set Empty')
16
+ return false
17
+ end
16
18
 
17
- def string_type?
18
- false
19
+ matches = @remote_set.subset? local_set(args[:attributes], @attribute)
20
+ SplitLogger.log_if_debug("[ContainsAllMatcher] Remote Set #{@remote_set} contains #{@attribute} -> #{matches}")
21
+ matches
19
22
  end
20
23
  end
21
24
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class ContainsAnyMatcher < SetMatcher
3
- MATCHER_TYPE = 'CONTAINS_ANY'.freeze
5
+ MATCHER_TYPE = 'CONTAINS_ANY'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -9,11 +11,10 @@ module SplitIoClient
9
11
  end
10
12
 
11
13
  def match?(args)
12
- local_set(args[:attributes], @attribute).intersect? @remote_set
13
- end
14
-
15
- def string_type?
16
- false
14
+ matches = local_set(args[:attributes], @attribute).intersect? @remote_set
15
+ SplitLogger.log_if_debug("[ContainsAnyMatcher] Remote Set #{@remote_set} contains any \
16
+ #{@attribute} or #{args[:attributes]}-> #{matches}")
17
+ matches
17
18
  end
18
19
  end
19
20
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class ContainsMatcher
3
- MATCHER_TYPE = 'CONTAINS_WITH'.freeze
5
+ MATCHER_TYPE = 'CONTAINS_WITH'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -10,21 +12,30 @@ module SplitIoClient
10
12
  end
11
13
 
12
14
  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?
15
+ SplitLogger.log_if_debug('[ContainsMatcher] evaluating value and attributes.')
16
16
 
17
- value = args[:value] || args[:attributes].fetch(@attribute) do |a|
18
- args[:attributes][a.to_s] || args[:attributes][a.to_sym]
19
- end
17
+ return false unless SplitIoClient::Validators.valid_matcher_arguments(args)
20
18
 
19
+ value = get_value(args)
20
+
21
+ SplitLogger.log_if_debug("[ContainsMatcher] Value from parameters: #{value}.")
21
22
  return false if @substr_list.empty?
22
23
 
23
- @substr_list.any? { |substr| value.to_s.include? substr }
24
+ matches = @substr_list.any? { |substr| value.to_s.include? substr }
25
+ SplitLogger.log_if_debug("[ContainsMatcher] #{@value} contains any of #{@substr_list} -> #{matches} .")
26
+ matches
24
27
  end
25
28
 
26
29
  def string_type?
27
30
  true
28
31
  end
32
+
33
+ private
34
+
35
+ def get_value(args)
36
+ args[:value] || args[:attributes].fetch(@attribute) do |a|
37
+ args[:attributes][a.to_s] || args[:attributes][a.to_sym]
38
+ end
39
+ end
29
40
  end
30
41
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class DependencyMatcher
3
- MATCHER_TYPE = 'IN_SPLIT_TREATMENT'.freeze
5
+ MATCHER_TYPE = 'IN_SPLIT_TREATMENT'
4
6
 
5
7
  def initialize(split, treatments)
6
8
  @split = split
@@ -9,8 +11,11 @@ module SplitIoClient
9
11
 
10
12
  def match?(args)
11
13
  keys = { matching_key: args[:matching_key], bucketing_key: args[:bucketing_key] }
12
-
13
- @treatments.include?(args[:evaluator].call(keys, @split, args[:attributes])[:treatment])
14
+ evaluate = args[:evaluator].call(keys, @split, args[:attributes])
15
+ matches = @treatments.include?(evaluate[:treatment])
16
+ SplitLogger.log_if_debug("[dependencyMatcher] Parent split #{@split} evaluated to #{evaluate[:treatment]} \
17
+ with label #{evaluate[:label]}. #{@split} evaluated treatment is part of [#{@treatments}] ? #{matches}.")
18
+ matches
14
19
  end
15
20
 
16
21
  def string_type?
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class EndsWithMatcher
3
- MATCHER_TYPE = 'ENDS_WITH'.freeze
5
+ MATCHER_TYPE = 'ENDS_WITH'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -10,17 +12,30 @@ module SplitIoClient
10
12
  end
11
13
 
12
14
  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
15
+ value = get_value(args)
16
16
 
17
- return false if @suffix_list.empty?
17
+ SplitLogger.log_if_debug("[EndsWithMatcher] Value from parameters: #{value}.")
18
+
19
+ if @suffix_list.empty?
20
+ SplitLogger.log_if_debug('[EndsWithMatcher] Sufix List empty.')
21
+ return false
22
+ end
18
23
 
19
- @suffix_list.any? { |suffix| value.to_s.end_with? suffix }
24
+ matches = @suffix_list.any? { |suffix| value.to_s.end_with? suffix }
25
+ SplitLogger.log_if_debug("[EndsWithMatcher] #{value} ends with any #{@suffix_list}")
26
+ matches
20
27
  end
21
28
 
22
29
  def string_type?
23
30
  true
24
31
  end
32
+
33
+ private
34
+
35
+ def get_value(args)
36
+ args[:value] || args[:attributes].fetch(@attribute) do |a|
37
+ args[:attributes][a.to_s] || args[:attributes][a.to_sym]
38
+ end
39
+ end
25
40
  end
26
41
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class EqualToBooleanMatcher
3
- MATCHER_TYPE = 'EQUAL_TO_BOOLEAN'.freeze
5
+ MATCHER_TYPE = 'EQUAL_TO_BOOLEAN'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -10,18 +12,25 @@ module SplitIoClient
10
12
  end
11
13
 
12
14
  def match?(args)
13
- value = args[:attributes].fetch(@attribute) do |a|
14
- args[:attributes][a.to_s] || args[:attributes][a.to_sym]
15
- end
15
+ value = get_value(args)
16
+ value = false if value.to_s.casecmp('false').zero?
17
+ value = true if value.to_s.casecmp('true').zero?
16
18
 
17
- value = false if value.to_s.downcase == 'false'
18
- value = true if value.to_s.downcase == 'true'
19
-
20
- value == @boolean
19
+ matches = value == @boolean
20
+ SplitLogger.log_if_debug("[EqualToBooleanMatcher] #{value} equals to #{@boolean} -> #{matches}")
21
+ matches
21
22
  end
22
23
 
23
24
  def string_type?
24
25
  false
25
26
  end
27
+
28
+ private
29
+
30
+ def get_value(args)
31
+ args[:attributes].fetch(@attribute) do |a|
32
+ args[:attributes][a.to_s] || args[:attributes][a.to_sym]
33
+ end
34
+ end
26
35
  end
27
36
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
- class EqualToMatcher
3
- MATCHER_TYPE = 'EQUAL_TO'.freeze
4
+ class EqualToMatcher < Matcher
5
+ MATCHER_TYPE = 'EQUAL_TO'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -11,29 +13,15 @@ module SplitIoClient
11
13
  end
12
14
 
13
15
  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])
16
+ SplitLogger.log_if_debug('[EqualsToMatcher] evaluating value and attributes.')
19
17
 
20
- value.is_a?(Integer) ? (value == @value) : false
21
- end
18
+ return false unless SplitIoClient::Validators.valid_matcher_arguments(args)
22
19
 
23
- def equals?(obj)
24
- if obj.nil?
25
- false
26
- elsif !obj.instance_of?(EqualToMatcher)
27
- false
28
- elsif self.equal?(obj)
29
- true
30
- else
31
- false
32
- end
33
- end
20
+ value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
34
21
 
35
- def string_type?
36
- false
22
+ matches = value.is_a?(Integer) ? (value == @value) : false
23
+ SplitLogger.log_if_debug("[EqualsToMatcher] #{value} equals to #{@value} -> #{matches}")
24
+ matches
37
25
  end
38
26
 
39
27
  private
@@ -43,7 +31,7 @@ module SplitIoClient
43
31
  when 'NUMBER'
44
32
  value
45
33
  when 'DATETIME'
46
- value = value / 1000 if sdk_data
34
+ value /= 1000 if sdk_data
47
35
 
48
36
  SplitIoClient::Utilities.to_milis_zero_out_from_hour value
49
37
  else
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
4
  class EqualToSetMatcher < SetMatcher
3
- MATCHER_TYPE = 'EQUAL_TO_SET'.freeze
5
+ MATCHER_TYPE = 'EQUAL_TO_SET'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -9,11 +11,10 @@ module SplitIoClient
9
11
  end
10
12
 
11
13
  def match?(args)
12
- local_set(args[:attributes], @attribute) == @remote_set
13
- end
14
-
15
- def string_type?
16
- false
14
+ set = local_set(args[:attributes], @attribute)
15
+ matches = set == @remote_set
16
+ SplitLogger.log_if_debug("[EqualsToSetMatcher] #{set} equals to #{@remote_set} -> #{matches}")
17
+ matches
17
18
  end
18
19
  end
19
20
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SplitIoClient
2
- class GreaterThanOrEqualToMatcher
3
- MATCHER_TYPE = 'GREATER_THAN_OR_EQUAL_TO'.freeze
4
+ class GreaterThanOrEqualToMatcher < Matcher
5
+ MATCHER_TYPE = 'GREATER_THAN_OR_EQUAL_TO'
4
6
 
5
7
  attr_reader :attribute
6
8
 
@@ -11,29 +13,15 @@ module SplitIoClient
11
13
  end
12
14
 
13
15
  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])
16
+ SplitLogger.log_if_debug('[GreaterThanOrEqualToMatcher] evaluating value and attributes.')
19
17
 
20
- value.is_a?(Integer) ? (value >= @value) : false
21
- end
18
+ return false unless SplitIoClient::Validators.valid_matcher_arguments(args)
22
19
 
23
- def equals?(obj)
24
- if obj.nil?
25
- false
26
- elsif !obj.instance_of?(GreaterThanOrEqualToMatcher)
27
- false
28
- elsif self.equal?(obj)
29
- true
30
- else
31
- false
32
- end
33
- end
20
+ value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
34
21
 
35
- def string_type?
36
- false
22
+ matches = value.is_a?(Integer) ? (value >= @value) : false
23
+ SplitLogger.log_if_debug("[GreaterThanOrEqualToMatcher] #{value} greater than or equal to #{@value} -> #{matches}")
24
+ matches
37
25
  end
38
26
 
39
27
  private
@@ -41,10 +29,10 @@ module SplitIoClient
41
29
  def formatted_value(value, sdk_data = false)
42
30
  case @data_type
43
31
  when 'NUMBER'
44
- return value
32
+ value
45
33
  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)
34
+ value /= 1000 if sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_hour
35
+ SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
48
36
  else
49
37
  @logger.error('Invalid data type')
50
38
  end