hackle-ruby-sdk 1.0.0 → 2.0.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hackle/client.rb +186 -87
  3. data/lib/hackle/config.rb +59 -17
  4. data/lib/hackle/decision.rb +113 -0
  5. data/lib/hackle/event.rb +89 -0
  6. data/lib/hackle/internal/clock/clock.rb +47 -0
  7. data/lib/hackle/internal/concurrent/executors.rb +20 -0
  8. data/lib/hackle/internal/concurrent/schedule/scheduler.rb +12 -0
  9. data/lib/hackle/internal/concurrent/schedule/timer_scheduler.rb +30 -0
  10. data/lib/hackle/internal/config/parameter_config.rb +50 -0
  11. data/lib/hackle/internal/core/hackle_core.rb +182 -0
  12. data/lib/hackle/{decision → internal/evaluation/bucketer}/bucketer.rb +17 -15
  13. data/lib/hackle/internal/evaluation/evaluator/contextual/contextual_evaluator.rb +29 -0
  14. data/lib/hackle/internal/evaluation/evaluator/delegating/delegating_evaluator.rb +26 -0
  15. data/lib/hackle/internal/evaluation/evaluator/evaluator.rb +117 -0
  16. data/lib/hackle/internal/evaluation/evaluator/experiment/experiment_evaluation_flow_factory.rb +67 -0
  17. data/lib/hackle/internal/evaluation/evaluator/experiment/experiment_evaluator.rb +172 -0
  18. data/lib/hackle/internal/evaluation/evaluator/experiment/experiment_flow_evaluator.rb +241 -0
  19. data/lib/hackle/internal/evaluation/evaluator/experiment/experiment_resolver.rb +166 -0
  20. data/lib/hackle/internal/evaluation/evaluator/remoteconfig/remote_config_determiner.rb +48 -0
  21. data/lib/hackle/internal/evaluation/evaluator/remoteconfig/remote_config_evaluator.rb +174 -0
  22. data/lib/hackle/internal/evaluation/flow/evaluation_flow.rb +49 -0
  23. data/lib/hackle/internal/evaluation/flow/flow_evaluator.rb +11 -0
  24. data/lib/hackle/internal/evaluation/match/condition/condition_matcher.rb +11 -0
  25. data/lib/hackle/internal/evaluation/match/condition/condition_matcher_factory.rb +53 -0
  26. data/lib/hackle/internal/evaluation/match/condition/experiment/experiment_condition_matcher.rb +29 -0
  27. data/lib/hackle/internal/evaluation/match/condition/experiment/experiment_evaluator_matcher.rb +135 -0
  28. data/lib/hackle/internal/evaluation/match/condition/segment/segment_condition_matcher.rb +67 -0
  29. data/lib/hackle/internal/evaluation/match/condition/user/user_condition_matcher.rb +44 -0
  30. data/lib/hackle/internal/evaluation/match/operator/operator_matcher.rb +185 -0
  31. data/lib/hackle/internal/evaluation/match/operator/operator_matcher_factory.rb +31 -0
  32. data/lib/hackle/internal/evaluation/match/target/target_matcher.rb +31 -0
  33. data/lib/hackle/internal/evaluation/match/value/value_matcher.rb +96 -0
  34. data/lib/hackle/internal/evaluation/match/value/value_matcher_factory.rb +28 -0
  35. data/lib/hackle/internal/evaluation/match/value/value_operator_matcher.rb +59 -0
  36. data/lib/hackle/internal/event/user_event.rb +187 -0
  37. data/lib/hackle/internal/event/user_event_dispatcher.rb +156 -0
  38. data/lib/hackle/internal/event/user_event_factory.rb +58 -0
  39. data/lib/hackle/internal/event/user_event_processor.rb +181 -0
  40. data/lib/hackle/internal/http/http.rb +28 -0
  41. data/lib/hackle/internal/http/http_client.rb +48 -0
  42. data/lib/hackle/internal/identifiers/identifier_builder.rb +67 -0
  43. data/lib/hackle/internal/logger/logger.rb +31 -0
  44. data/lib/hackle/internal/model/action.rb +57 -0
  45. data/lib/hackle/internal/model/bucket.rb +58 -0
  46. data/lib/hackle/internal/model/container.rb +47 -0
  47. data/lib/hackle/internal/model/decision_reason.rb +31 -0
  48. data/lib/hackle/{models → internal/model}/event_type.rb +5 -8
  49. data/lib/hackle/internal/model/experiment.rb +194 -0
  50. data/lib/hackle/internal/model/parameter_configuration.rb +19 -0
  51. data/lib/hackle/internal/model/remote_config_parameter.rb +76 -0
  52. data/lib/hackle/internal/model/sdk.rb +23 -0
  53. data/lib/hackle/internal/model/segment.rb +61 -0
  54. data/lib/hackle/internal/model/target.rb +203 -0
  55. data/lib/hackle/internal/model/target_rule.rb +19 -0
  56. data/lib/hackle/internal/model/targeting.rb +45 -0
  57. data/lib/hackle/internal/model/value_type.rb +75 -0
  58. data/lib/hackle/internal/model/variation.rb +27 -0
  59. data/lib/hackle/internal/model/version.rb +153 -0
  60. data/lib/hackle/internal/properties/properties_builder.rb +101 -0
  61. data/lib/hackle/internal/user/hackle_user.rb +74 -0
  62. data/lib/hackle/internal/user/hackle_user_resolver.rb +27 -0
  63. data/lib/hackle/internal/workspace/http_workspace_fetcher.rb +50 -0
  64. data/lib/hackle/internal/workspace/polling_workspace_fetcher.rb +62 -0
  65. data/lib/hackle/internal/workspace/workspace.rb +353 -0
  66. data/lib/hackle/internal/workspace/workspace_fetcher.rb +18 -0
  67. data/lib/hackle/remote_config.rb +55 -0
  68. data/lib/hackle/user.rb +124 -0
  69. data/lib/hackle/version.rb +1 -11
  70. data/lib/hackle.rb +4 -69
  71. metadata +123 -53
  72. data/.gitignore +0 -11
  73. data/.rspec +0 -2
  74. data/.travis.yml +0 -7
  75. data/Gemfile +0 -6
  76. data/README.md +0 -33
  77. data/Rakefile +0 -6
  78. data/hackle-ruby-sdk.gemspec +0 -29
  79. data/lib/hackle/decision/decider.rb +0 -69
  80. data/lib/hackle/events/event_dispatcher.rb +0 -96
  81. data/lib/hackle/events/event_processor.rb +0 -126
  82. data/lib/hackle/events/user_event.rb +0 -61
  83. data/lib/hackle/http/http.rb +0 -37
  84. data/lib/hackle/models/bucket.rb +0 -26
  85. data/lib/hackle/models/event.rb +0 -26
  86. data/lib/hackle/models/experiment.rb +0 -69
  87. data/lib/hackle/models/slot.rb +0 -22
  88. data/lib/hackle/models/user.rb +0 -24
  89. data/lib/hackle/models/variation.rb +0 -21
  90. data/lib/hackle/workspaces/http_workspace_fetcher.rb +0 -24
  91. data/lib/hackle/workspaces/polling_workspace_fetcher.rb +0 -47
  92. data/lib/hackle/workspaces/workspace.rb +0 -100
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+
5
+ class Container
6
+ # @!attribute [r] id
7
+ # @return [Integer]
8
+ # @!attribute [r] bucket_id
9
+ # @return [Integer]
10
+ # @!attribute [r] groups
11
+ # @return [Array<ContainerGroup>]
12
+ attr_reader :id, :bucket_id, :groups
13
+
14
+ # @param id [Integer]
15
+ # @param bucket_id [Integer]
16
+ # @param groups [Array<ContainerGroup>]
17
+ def initialize(id:, bucket_id:, groups:)
18
+ @id = id
19
+ @bucket_id = bucket_id
20
+ @groups = groups
21
+ end
22
+
23
+ # @param group_id [Integer]
24
+ # @return [ContainerGroup, nil]
25
+ def get_group_or_nil(group_id)
26
+ groups.each do |group|
27
+ return group if group.id == group_id
28
+ end
29
+ nil
30
+ end
31
+ end
32
+
33
+ class ContainerGroup
34
+ # @!attribute [r] id
35
+ # @return [Integer]
36
+ # @!attribute [r] experiments
37
+ # @return [Array<Integer>]
38
+ attr_reader :id, :experiments
39
+
40
+ # @param id [Integer]
41
+ # @param experiments [Array<Integer>]
42
+ def initialize(id:, experiments:)
43
+ @id = id
44
+ @experiments = experiments
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class DecisionReason
5
+ SDK_NOT_READY = 'SDK_NOT_READY'
6
+ EXCEPTION = 'EXCEPTION'
7
+ INVALID_INPUT = 'INVALID_INPUT'
8
+
9
+ EXPERIMENT_NOT_FOUND = 'EXPERIMENT_NOT_FOUND'
10
+ EXPERIMENT_DRAFT = 'EXPERIMENT_DRAFT'
11
+ EXPERIMENT_PAUSED = 'EXPERIMENT_PAUSED'
12
+ EXPERIMENT_COMPLETED = 'EXPERIMENT_COMPLETED'
13
+ OVERRIDDEN = 'OVERRIDDEN'
14
+ TRAFFIC_NOT_ALLOCATED = 'TRAFFIC_NOT_ALLOCATED'
15
+ TRAFFIC_ALLOCATED = 'TRAFFIC_ALLOCATED'
16
+ TRAFFIC_ALLOCATED_BY_TARGETING = 'TRAFFIC_ALLOCATED_BY_TARGETING'
17
+ VARIATION_DROPPED = 'VARIATION_DROPPED'
18
+ NOT_IN_EXPERIMENT_TARGET = 'NOT_IN_EXPERIMENT_TARGET'
19
+ NOT_IN_MUTUAL_EXCLUSION_EXPERIMENT = 'NOT_IN_MUTUAL_EXCLUSION_EXPERIMENT'
20
+ IDENTIFIER_NOT_FOUND = 'IDENTIFIER_NOT_FOUND'
21
+
22
+ FEATURE_FLAG_NOT_FOUND = 'FEATURE_FLAG_NOT_FOUND'
23
+ FEATURE_FLAG_INACTIVE = 'FEATURE_FLAG_INACTIVE'
24
+ INDIVIDUAL_TARGET_MATCH = 'INDIVIDUAL_TARGET_MATCH'
25
+ TARGET_RULE_MATCH = 'TARGET_RULE_MATCH'
26
+ DEFAULT_RULE = 'DEFAULT_RULE'
27
+
28
+ REMOTE_CONFIG_PARAMETER_NOT_FOUND = 'REMOTE_CONFIG_PARAMETER_NOT_FOUND'
29
+ TYPE_MISMATCH = 'TYPE_MISMATCH'
30
+ end
31
+ end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hackle
2
4
  class EventType
3
5
 
4
6
  # @!attribute [r] id
5
- # @return [Integer]
7
+ # @return [Integer]
6
8
  # @!attribute [r] key
7
- # @return [String]
8
- attr_reader :id, :key
9
+ # @return [String]
10
+ attr_accessor :id, :key
9
11
 
10
12
  # @param id [Integer]
11
13
  # @param key [String]
@@ -13,10 +15,5 @@ module Hackle
13
15
  @id = id
14
16
  @key = key
15
17
  end
16
-
17
- # @param key [String]
18
- def self.undefined(key:)
19
- EventType.new(id: 0, key: key)
20
- end
21
18
  end
22
19
  end
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class Experiment
5
+ # @return [Integer]
6
+ attr_reader :id
7
+
8
+ # @return [Integer]
9
+ attr_reader :key
10
+
11
+ # @return [String, nil]
12
+ attr_reader :name
13
+
14
+ # @return [ExperimentType]
15
+ attr_reader :type
16
+
17
+ # @return [String]
18
+ attr_reader :identifier_type
19
+
20
+ # @return [ExperimentStatus]
21
+ attr_reader :status
22
+
23
+ # @return [Integer]
24
+ attr_reader :version
25
+
26
+ # @return [Integer]
27
+ attr_reader :execution_version
28
+
29
+ # @return [Array<Variation>]
30
+ attr_reader :variations
31
+
32
+ # @return [Hash{String => Integer}]
33
+ attr_reader :user_overrides
34
+
35
+ # @return [Array<TargetRule>]
36
+ attr_reader :segment_overrides
37
+
38
+ # @return [Array<Target>]
39
+ attr_reader :target_audiences
40
+
41
+ # @return [Array<TargetRule>]
42
+ attr_reader :target_rules
43
+
44
+ # @return [Action]
45
+ attr_reader :default_rule
46
+
47
+ # @return [Integer, nil]
48
+ attr_reader :container_id
49
+
50
+ # @return [Integer, nil]
51
+ attr_reader :winner_variation_id
52
+
53
+ # @param [Integer] id
54
+ # @param [Integer] key
55
+ # @param [String, nil] name
56
+ # @param [ExperimentType] type
57
+ # @param [String] identifier_type
58
+ # @param [ExperimentStatus] status
59
+ # @param [Integer] version
60
+ # @param [Integer] execution_version
61
+ # @param [Array<Variation>] variations
62
+ # @param [Hash{String => Integer}] user_overrides
63
+ # @param [Array<TargetRule>] segment_overrides
64
+ # @param [Array<Target>] target_audiences
65
+ # @param [Array<TargetRule>] target_rules
66
+ # @param [Action] default_rule
67
+ # @param [Integer, nil] container_id
68
+ # @param [Integer, nil] winner_variation_id
69
+ def initialize(
70
+ id:,
71
+ key:,
72
+ name:,
73
+ type:,
74
+ identifier_type:,
75
+ status:,
76
+ version:,
77
+ execution_version:,
78
+ variations:,
79
+ user_overrides:,
80
+ segment_overrides:,
81
+ target_audiences:,
82
+ target_rules:,
83
+ default_rule:,
84
+ container_id:,
85
+ winner_variation_id:
86
+ )
87
+ @id = id
88
+ @key = key
89
+ @name = name
90
+ @type = type
91
+ @identifier_type = identifier_type
92
+ @status = status
93
+ @version = version
94
+ @execution_version = execution_version
95
+ @variations = variations
96
+ @user_overrides = user_overrides
97
+ @segment_overrides = segment_overrides
98
+ @target_audiences = target_audiences
99
+ @target_rules = target_rules
100
+ @default_rule = default_rule
101
+ @container_id = container_id
102
+ @winner_variation_id = winner_variation_id
103
+ end
104
+
105
+ # @param id [Integer]
106
+ # @return [Hackle::Variation, nil]
107
+ def get_variation_or_nil_by_id(id)
108
+ variations.find { |v| v.id == id }
109
+ end
110
+
111
+ # @param key [String]
112
+ # @return [Hackle::Variation, nil]
113
+ def get_variation_or_nil_by_key(key)
114
+ variations.find { |v| v.key == key }
115
+ end
116
+
117
+ # @return [Hackle::Variation, nil]
118
+ def winner_variation_or_nil
119
+ get_variation_or_nil_by_id(winner_variation_id) unless winner_variation_id.nil?
120
+ end
121
+ end
122
+
123
+ class ExperimentType
124
+ # @!attribute [r] name
125
+ # @return [String]
126
+ attr_reader :name
127
+
128
+ # @param name [String]
129
+ def initialize(name)
130
+ @name = name
131
+ end
132
+
133
+ def to_s
134
+ name
135
+ end
136
+
137
+ AB_TEST = new('AB_TEST')
138
+ FEATURE_FLAG = new('FEATURE_FLAG')
139
+
140
+ @types = {
141
+ 'AB_TEST' => AB_TEST,
142
+ 'FEATURE_FLAG' => FEATURE_FLAG
143
+ }.freeze
144
+
145
+ # @param name [String]
146
+ # @return [ExperimentType, nil]
147
+ def self.from_or_nil(name)
148
+ @types[name.upcase]
149
+ end
150
+
151
+ # @return [Array<ExperimentType>]
152
+ def self.values
153
+ @types.values
154
+ end
155
+ end
156
+
157
+ class ExperimentStatus
158
+ # @!attribute [r] name
159
+ # @return [String]
160
+ attr_reader :name
161
+
162
+ # @param name [String]
163
+ def initialize(name)
164
+ @name = name
165
+ end
166
+
167
+ def to_s
168
+ name
169
+ end
170
+
171
+ DRAFT = new('DRAFT')
172
+ RUNNING = new('RUNNING')
173
+ PAUSED = new('PAUSED')
174
+ COMPLETED = new('COMPLETED')
175
+
176
+ @types = {
177
+ 'READY' => DRAFT,
178
+ 'RUNNING' => RUNNING,
179
+ 'PAUSED' => PAUSED,
180
+ 'STOPPED' => COMPLETED
181
+ }.freeze
182
+
183
+ # @param name [String]
184
+ # @return [ExperimentStatus, nil]
185
+ def self.from_or_nil(name)
186
+ @types[name.upcase]
187
+ end
188
+
189
+ # @return [Array<ExperimentStatus>]
190
+ def self.values
191
+ @types.values
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class ParameterConfiguration
5
+
6
+ # @!attribute [r] id
7
+ # @return [Integer]
8
+ # @!attribute [r] parameters
9
+ # @return [Hash{String => Object}]
10
+ attr_accessor :id, :parameters
11
+
12
+ # @param id [Integer]
13
+ # @param parameters [Hash{String => Object}]
14
+ def initialize(id:, parameters:)
15
+ @id = id
16
+ @parameters = parameters
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+
5
+ class RemoteConfigParameter
6
+ # @!attribute [r] id
7
+ # @return [Integer]
8
+ # @!attribute [r] key
9
+ # @return [String]
10
+ # @!attribute [r] type
11
+ # @return [ValueType]
12
+ # @!attribute [r] identifier_type
13
+ # @return [String]
14
+ # @!attribute [r] target_rules
15
+ # @return [Array<RemoteConfigTargetRule>]
16
+ # @!attribute [r] default_value
17
+ # @return [RemoteConfigValue]
18
+ attr_accessor :id, :key, :type, :identifier_type, :target_rules, :default_value
19
+
20
+ # @param id [Integer]
21
+ # @param key [String]
22
+ # @param type [ValueType]
23
+ # @param identifier_type [String]
24
+ # @param target_rules [Array<RemoteConfigTargetRule>]
25
+ # @param default_value [RemoteConfigValue]
26
+ def initialize(id:, key:, type:, identifier_type:, target_rules:, default_value:)
27
+ @id = id
28
+ @key = key
29
+ @type = type
30
+ @identifier_type = identifier_type
31
+ @target_rules = target_rules
32
+ @default_value = default_value
33
+ end
34
+ end
35
+
36
+ class RemoteConfigTargetRule
37
+ # @!attribute [r] key
38
+ # @return [String]
39
+ # @!attribute [r] name
40
+ # @return [String]
41
+ # @!attribute [r] target
42
+ # @return [Target]
43
+ # @!attribute [r] bucket_id
44
+ # @return [Integer]
45
+ # @!attribute [r] value
46
+ # @return [RemoteConfigValue]
47
+ attr_reader :key, :name, :target, :bucket_id, :value
48
+
49
+ # @param key [String]
50
+ # @param name [String]
51
+ # @param target [Target]
52
+ # @param bucket_id [Integer]
53
+ # @param value [RemoteConfigValue]
54
+ def initialize(key:, name:, target:, bucket_id:, value:)
55
+ @key = key
56
+ @name = name
57
+ @target = target
58
+ @bucket_id = bucket_id
59
+ @value = value
60
+
61
+ end
62
+ end
63
+
64
+ class RemoteConfigValue
65
+ # @!attribute [r] id
66
+ # @return [Integer]
67
+ # @!attribute [r] raw_value
68
+ # @return [Object]
69
+ attr_accessor :id, :raw_value
70
+
71
+ def initialize(id:, raw_value:)
72
+ @id = id
73
+ @raw_value = raw_value
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class Sdk
5
+
6
+ # @!attribute [r] name
7
+ # @return [String]
8
+ # @!attribute [r] version
9
+ # @return [String]
10
+ # @!attribute [r] key
11
+ # @return [String]
12
+ attr_reader :name, :version, :key
13
+
14
+ # @param name [String]
15
+ # @param version [String]
16
+ # @param key [String]
17
+ def initialize(name:, version:, key:)
18
+ @name = name
19
+ @version = version
20
+ @key = key
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class Segment
5
+
6
+ # @!attribute [r] id
7
+ # @return [Integer]
8
+ # @!attribute [r] key
9
+ # @return [String]
10
+ # @!attribute [r] type
11
+ # @return [SegmentType]
12
+ # @!attribute [r] targets
13
+ # @return [Array<Target>]
14
+ attr_accessor :id, :key, :type, :targets
15
+
16
+ # @param id [Integer]
17
+ # @param key [String]
18
+ # @param type [SegmentType]
19
+ # @param targets [Array<Target>]
20
+ def initialize(id:, key:, type:, targets:)
21
+ @id = id
22
+ @key = key
23
+ @type = type
24
+ @targets = targets
25
+ end
26
+ end
27
+
28
+ class SegmentType
29
+ # @!attribute [r] name
30
+ # @return [String]
31
+ attr_reader :name
32
+
33
+ # @param name [String]
34
+ def initialize(name)
35
+ @name = name
36
+ end
37
+
38
+ def to_s
39
+ name
40
+ end
41
+
42
+ USER_ID = new('USER_ID')
43
+ USER_PROPERTY = new('USER_PROPERTY')
44
+
45
+ @types = {
46
+ 'USER_ID' => USER_ID,
47
+ 'USER_PROPERTY' => USER_PROPERTY
48
+ }.freeze
49
+
50
+ # @param name [String]
51
+ # @return [SegmentType, nil]
52
+ def self.from_or_nil(name)
53
+ @types[name.upcase]
54
+ end
55
+
56
+ # @return [Array<SegmentType>]
57
+ def self.values
58
+ @types.values
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class Target
5
+ # @!attribute [r] conditions
6
+ # @return [Array<TargetCondition>]
7
+ attr_reader :conditions
8
+
9
+ # @param conditions [Array<TargetCondition>]
10
+ def initialize(conditions:)
11
+ @conditions = conditions
12
+ end
13
+ end
14
+
15
+ class TargetCondition
16
+ # @!attribute [r] key
17
+ # @return [TargetKey]
18
+ # @!attribute [r] match
19
+ # @return [TargetMatch]
20
+ attr_reader :key, :match
21
+
22
+ def initialize(key:, match:)
23
+ @key = key
24
+ @match = match
25
+ end
26
+ end
27
+
28
+ class TargetKey
29
+ # @!attribute [r] type
30
+ # @return [TargetKeyType]
31
+ # @!attribute [r] name
32
+ # @return [String]
33
+ attr_reader :type, :name
34
+
35
+ # @param type [TargetKeyType]
36
+ # @param name [String]
37
+ def initialize(type:, name:)
38
+ @type = type
39
+ @name = name
40
+ end
41
+ end
42
+
43
+ class TargetMatch
44
+
45
+ # @!attribute [r] type
46
+ # @return [TargetMatchType]
47
+ # @!attribute [r] operator
48
+ # @return [TargetOperator]
49
+ # @!attribute [r] value_type
50
+ # @return [ValueType]
51
+ # @!attribute [r] values
52
+ # @return [Array<Object>]
53
+ attr_reader :type, :operator, :value_type, :values
54
+
55
+ # @param type [TargetMatchType]
56
+ # @param operator [TargetOperator]
57
+ # @param value_type [ValueType]
58
+ # @param values [Array<Object>]
59
+ def initialize(type:, operator:, value_type:, values:)
60
+ @type = type
61
+ @operator = operator
62
+ @value_type = value_type
63
+ @values = values
64
+ end
65
+
66
+ end
67
+
68
+ class TargetKeyType
69
+ # @!attribute [r] name
70
+ # @return [String]
71
+ attr_reader :name
72
+
73
+ # @param name [String]
74
+ def initialize(name)
75
+ @name = name
76
+ end
77
+
78
+ def to_s
79
+ name
80
+ end
81
+
82
+ USER_ID = new('USER_ID')
83
+ USER_PROPERTY = new('USER_PROPERTY')
84
+ HACKLE_PROPERTY = new('HACKLE_PROPERTY')
85
+ SEGMENT = new('SEGMENT')
86
+ AB_TEST = new('AB_TEST')
87
+ FEATURE_FLAG = new('FEATURE_FLAG')
88
+
89
+ @types = {
90
+ 'USER_ID' => USER_ID,
91
+ 'USER_PROPERTY' => USER_PROPERTY,
92
+ 'HACKLE_PROPERTY' => HACKLE_PROPERTY,
93
+ 'SEGMENT' => SEGMENT,
94
+ 'AB_TEST' => AB_TEST,
95
+ 'FEATURE_FLAG' => FEATURE_FLAG
96
+ }.freeze
97
+
98
+ # @param name [String]
99
+ # @return [TargetKeyType, nil]
100
+ def self.from_or_nil(name)
101
+ @types[name.upcase]
102
+ end
103
+
104
+ # @return [Array<TargetKeyType>]
105
+ def self.values
106
+ @types.values
107
+ end
108
+ end
109
+
110
+ class TargetMatchType
111
+ # @!attribute [r] name
112
+ # @return [String]
113
+ attr_reader :name
114
+
115
+ # @param name [String]
116
+ def initialize(name)
117
+ @name = name
118
+ end
119
+
120
+ def to_s
121
+ name
122
+ end
123
+
124
+ MATCH = new('MATCH')
125
+ NOT_MATCH = new('NOT MATCH')
126
+
127
+ @types = {
128
+ 'MATCH' => MATCH,
129
+ 'NOT_MATCH' => NOT_MATCH
130
+ }
131
+
132
+ # @param name [String]
133
+ # @return [TargetMatchType, nil]
134
+ def self.from_or_nil(name)
135
+ @types[name.upcase]
136
+ end
137
+
138
+ # @return [Array<TargetMatchType>]
139
+ def self.values
140
+ @types.values
141
+ end
142
+
143
+ # @param type [TargetMatchType]
144
+ # @param matches [boolean]
145
+ # @return [boolean]
146
+ def self.matches(type, matches)
147
+ case type
148
+ when MATCH
149
+ matches
150
+ when NOT_MATCH
151
+ !matches
152
+ else
153
+ raise ArgumentError, "Unsupported type: #{type}"
154
+ end
155
+ end
156
+ end
157
+
158
+ class TargetOperator
159
+ # @!attribute [r] name
160
+ # @return [String]
161
+ attr_reader :name
162
+
163
+ # @param name [String]
164
+ def initialize(name)
165
+ @name = name
166
+ end
167
+
168
+ def to_s
169
+ name
170
+ end
171
+
172
+ IN = new('IN')
173
+ CONTAINS = new('CONTAINS')
174
+ STARTS_WITH = new('STARTS_WITH')
175
+ ENDS_WITH = new('ENDS_WITH')
176
+ GT = new('GT')
177
+ GTE = new('GTE')
178
+ LT = new('LT')
179
+ LTE = new('LTE')
180
+
181
+ @types = {
182
+ 'IN' => IN,
183
+ 'CONTAINS' => CONTAINS,
184
+ 'STARTS_WITH' => STARTS_WITH,
185
+ 'ENDS_WITH' => ENDS_WITH,
186
+ 'GT' => GT,
187
+ 'GTE' => GTE,
188
+ 'LT' => LT,
189
+ 'LTE' => LTE
190
+ }.freeze
191
+
192
+ # @param name [String]
193
+ # @return [TargetOperator, nil]
194
+ def self.from_or_nil(name)
195
+ @types[name.upcase]
196
+ end
197
+
198
+ # @return [Array<TargetOperator>]
199
+ def self.values
200
+ @types.values
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hackle
4
+ class TargetRule
5
+
6
+ # @!attribute [r] target
7
+ # @return [Target]
8
+ # @!attribute [r] action
9
+ # @return [Action]
10
+ attr_accessor :target, :action
11
+
12
+ # @param target [Target]
13
+ # @param action [Action]
14
+ def initialize(target:, action:)
15
+ @target = target
16
+ @action = action
17
+ end
18
+ end
19
+ end