configcat 5.0.2 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/configcat/configcache.rb +19 -4
- data/lib/configcat/configcatclient.rb +263 -107
- data/lib/configcat/configcatlogger.rb +24 -0
- data/lib/configcat/configcatoptions.rb +153 -0
- data/lib/configcat/configentry.rb +40 -0
- data/lib/configcat/configfetcher.rb +98 -40
- data/lib/configcat/configservice.rb +212 -0
- data/lib/configcat/evaluationdetails.rb +23 -0
- data/lib/configcat/interfaces.rb +4 -59
- data/lib/configcat/localdictionarydatasource.rb +14 -4
- data/lib/configcat/localfiledatasource.rb +22 -11
- data/lib/configcat/overridedatasource.rb +8 -2
- data/lib/configcat/pollingmode.rb +62 -0
- data/lib/configcat/refreshresult.rb +3 -0
- data/lib/configcat/rolloutevaluator.rb +32 -37
- data/lib/configcat/user.rb +18 -39
- data/lib/configcat/utils.rb +10 -0
- data/lib/configcat/version.rb +1 -1
- data/lib/configcat.rb +128 -136
- metadata +24 -5
- data/lib/configcat/autopollingcachepolicy.rb +0 -99
- data/lib/configcat/lazyloadingcachepolicy.rb +0 -69
- data/lib/configcat/manualpollingcachepolicy.rb +0 -47
data/lib/configcat/interfaces.rb
CHANGED
@@ -1,71 +1,16 @@
|
|
1
1
|
module ConfigCat
|
2
|
-
|
3
|
-
class ConfigFetcher
|
4
|
-
#
|
5
|
-
# Config fetcher interface
|
6
|
-
#
|
7
|
-
|
8
|
-
def get_configuration_json()
|
9
|
-
#
|
10
|
-
# :return: Returns the configuration json Dictionary
|
11
|
-
#
|
12
|
-
end
|
13
|
-
|
14
|
-
def close()
|
15
|
-
#
|
16
|
-
# Closes the ConfigFetcher's resources
|
17
|
-
#
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
2
|
+
# Config cache interface
|
21
3
|
class ConfigCache
|
22
|
-
#
|
23
|
-
# Config cache interface
|
24
|
-
#
|
25
|
-
|
4
|
+
# :returns the config json object from the cache
|
26
5
|
def get(key)
|
27
|
-
#
|
28
|
-
# :returns the config json object from the cache
|
29
|
-
#
|
30
6
|
end
|
31
7
|
|
8
|
+
# Sets the config json cache.
|
32
9
|
def set(key, value)
|
33
|
-
#
|
34
|
-
# Sets the config json cache.
|
35
|
-
#
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class CachePolicy
|
40
|
-
#
|
41
|
-
# Config cache interface
|
42
|
-
#
|
43
|
-
|
44
|
-
def get()
|
45
|
-
#
|
46
|
-
# :returns the config json object from the cache
|
47
|
-
#
|
48
|
-
end
|
49
|
-
|
50
|
-
def force_refresh()
|
51
|
-
#
|
52
|
-
#
|
53
|
-
# :return:
|
54
|
-
#
|
55
|
-
end
|
56
|
-
|
57
|
-
def stop()
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# :return:
|
61
|
-
#
|
62
10
|
end
|
63
11
|
end
|
64
12
|
|
13
|
+
# Generic ConfigCatClientException
|
65
14
|
class ConfigCatClientException < Exception
|
66
|
-
#
|
67
|
-
# Generic ConfigCatClientException
|
68
|
-
#
|
69
15
|
end
|
70
|
-
|
71
16
|
end
|
@@ -3,17 +3,27 @@ require 'configcat/constants'
|
|
3
3
|
|
4
4
|
|
5
5
|
module ConfigCat
|
6
|
+
class LocalDictionaryFlagOverrides < FlagOverrides
|
7
|
+
def initialize(source, override_behaviour)
|
8
|
+
@source = source
|
9
|
+
@override_behaviour = override_behaviour
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_data_source(log)
|
13
|
+
return LocalDictionaryDataSource.new(@source, @override_behaviour)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
6
17
|
class LocalDictionaryDataSource < OverrideDataSource
|
7
18
|
def initialize(source, override_behaviour)
|
8
19
|
super(override_behaviour)
|
9
|
-
|
20
|
+
@_settings = {}
|
10
21
|
source.each do |key, value|
|
11
|
-
|
22
|
+
@_settings[key] = { VALUE => value }
|
12
23
|
end
|
13
|
-
@_settings = {FEATURE_FLAGS => dictionary}
|
14
24
|
end
|
15
25
|
|
16
|
-
def get_overrides
|
26
|
+
def get_overrides
|
17
27
|
return @_settings
|
18
28
|
end
|
19
29
|
end
|
@@ -3,25 +3,37 @@ require 'configcat/constants'
|
|
3
3
|
|
4
4
|
|
5
5
|
module ConfigCat
|
6
|
-
class
|
6
|
+
class LocalFileFlagOverrides < FlagOverrides
|
7
7
|
def initialize(file_path, override_behaviour)
|
8
|
+
@file_path = file_path
|
9
|
+
@override_behaviour = override_behaviour
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_data_source(log)
|
13
|
+
return LocalFileDataSource.new(@file_path, @override_behaviour, log)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class LocalFileDataSource < OverrideDataSource
|
18
|
+
def initialize(file_path, override_behaviour, log)
|
8
19
|
super(override_behaviour)
|
9
|
-
|
10
|
-
|
20
|
+
@log = log
|
21
|
+
if !File.exists?(file_path)
|
22
|
+
@log.error("The file '%s' does not exists." % file_path)
|
11
23
|
end
|
12
24
|
@_file_path = file_path
|
13
25
|
@_settings = nil
|
14
26
|
@_cached_file_stamp = 0
|
15
27
|
end
|
16
28
|
|
17
|
-
def get_overrides
|
29
|
+
def get_overrides
|
18
30
|
reload_file_content()
|
19
31
|
return @_settings
|
20
32
|
end
|
21
33
|
|
22
34
|
private
|
23
35
|
|
24
|
-
def reload_file_content
|
36
|
+
def reload_file_content
|
25
37
|
begin
|
26
38
|
stamp = File.mtime(@_file_path)
|
27
39
|
if stamp != @_cached_file_stamp
|
@@ -29,20 +41,19 @@ module ConfigCat
|
|
29
41
|
file = File.read(@_file_path)
|
30
42
|
data = JSON.parse(file)
|
31
43
|
if data.key?("flags")
|
32
|
-
|
44
|
+
@_settings = {}
|
33
45
|
source = data["flags"]
|
34
46
|
source.each do |key, value|
|
35
|
-
|
47
|
+
@_settings[key] = { VALUE => value }
|
36
48
|
end
|
37
|
-
@_settings = {FEATURE_FLAGS => dictionary}
|
38
49
|
else
|
39
|
-
@_settings = data
|
50
|
+
@_settings = data[FEATURE_FLAGS]
|
40
51
|
end
|
41
52
|
end
|
42
53
|
rescue JSON::ParserError => e
|
43
|
-
|
54
|
+
@log.error("Could not decode json from file %s. %s" % [@_file_path, e.to_s])
|
44
55
|
rescue Exception => e
|
45
|
-
|
56
|
+
@log.error("Could not read the content of the file %s. %s" % [@_file_path, e.to_s])
|
46
57
|
end
|
47
58
|
end
|
48
59
|
end
|
@@ -15,16 +15,22 @@ module ConfigCat
|
|
15
15
|
REMOTE_OVER_LOCAL = 2
|
16
16
|
end
|
17
17
|
|
18
|
+
class FlagOverrides
|
19
|
+
# :returns [OverrideDataSource] the created OverrideDataSource
|
20
|
+
def create_data_source(log)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
18
24
|
class OverrideDataSource
|
19
25
|
def initialize(override_behaviour)
|
20
26
|
@_override_behaviour = override_behaviour
|
21
27
|
end
|
22
28
|
|
23
|
-
def get_behaviour
|
29
|
+
def get_behaviour
|
24
30
|
return @_override_behaviour
|
25
31
|
end
|
26
32
|
|
27
|
-
def get_overrides
|
33
|
+
def get_overrides
|
28
34
|
# :returns the override dictionary
|
29
35
|
return {}
|
30
36
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ConfigCat
|
2
|
+
class PollingMode
|
3
|
+
# Creates a configured auto polling configuration.
|
4
|
+
#
|
5
|
+
# :param poll_interval_seconds: sets at least how often this policy should fetch the latest configuration and refresh the cache.
|
6
|
+
# :param max_init_wait_time_seconds: sets the maximum waiting time between initialization and the first config acquisition in seconds.
|
7
|
+
# :return [AutoPollingMode]
|
8
|
+
def self.auto_poll(poll_interval_seconds: 60, max_init_wait_time_seconds: 5)
|
9
|
+
poll_interval_seconds = 1 if poll_interval_seconds < 1
|
10
|
+
max_init_wait_time_seconds = 0 if max_init_wait_time_seconds < 0
|
11
|
+
|
12
|
+
AutoPollingMode.new(poll_interval_seconds, max_init_wait_time_seconds)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Creates a configured lazy loading polling configuration.
|
16
|
+
#
|
17
|
+
# :param cache_refresh_interval_seconds: sets how long the cache will store its value before fetching the latest from the network again.
|
18
|
+
# :return [LazyLoadingMode]
|
19
|
+
def self.lazy_load(cache_refresh_interval_seconds: 60)
|
20
|
+
cache_refresh_interval_seconds = 1 if cache_refresh_interval_seconds < 1
|
21
|
+
|
22
|
+
LazyLoadingMode.new(cache_refresh_interval_seconds)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a configured manual polling configuration.
|
26
|
+
# :return [ManualPollingMode]
|
27
|
+
def self.manual_poll
|
28
|
+
ManualPollingMode.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class AutoPollingMode < PollingMode
|
33
|
+
attr_reader :poll_interval_seconds, :max_init_wait_time_seconds
|
34
|
+
|
35
|
+
def initialize(poll_interval_seconds, max_init_wait_time_seconds)
|
36
|
+
@poll_interval_seconds = poll_interval_seconds
|
37
|
+
@max_init_wait_time_seconds = max_init_wait_time_seconds
|
38
|
+
end
|
39
|
+
|
40
|
+
def identifier
|
41
|
+
return "a"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class LazyLoadingMode < PollingMode
|
46
|
+
attr_reader :cache_refresh_interval_seconds
|
47
|
+
|
48
|
+
def initialize(cache_refresh_interval_seconds)
|
49
|
+
@cache_refresh_interval_seconds = cache_refresh_interval_seconds
|
50
|
+
end
|
51
|
+
|
52
|
+
def identifier
|
53
|
+
return "l"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class ManualPollingMode < PollingMode
|
58
|
+
def identifier
|
59
|
+
return "m"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -7,36 +7,34 @@ module ConfigCat
|
|
7
7
|
class RolloutEvaluator
|
8
8
|
COMPARATOR_TEXTS = ["IS ONE OF", "IS NOT ONE OF", "CONTAINS", "DOES NOT CONTAIN", "IS ONE OF (SemVer)", "IS NOT ONE OF (SemVer)", "< (SemVer)", "<= (SemVer)", "> (SemVer)", ">= (SemVer)", "= (Number)", "<> (Number)", "< (Number)", "<= (Number)", "> (Number)", ">= (Number)"]
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
feature_flags = config.fetch(FEATURE_FLAGS, nil)
|
14
|
-
if feature_flags === nil
|
15
|
-
ConfigCat.logger.error("Evaluating get_value('%s') failed. Value not found for key '%s' Returning default_value: [%s]." % [key, key, default_value.to_s])
|
16
|
-
return default_value, default_variation_id
|
17
|
-
end
|
10
|
+
def initialize(log)
|
11
|
+
@log = log
|
12
|
+
end
|
18
13
|
|
19
|
-
|
14
|
+
# :returns value, variation_id. matched_evaluation_rule, matched_evaluation_percentage_rule, error
|
15
|
+
def evaluate(key:, user:, default_value:, default_variation_id:, settings:)
|
16
|
+
setting_descriptor = settings[key]
|
20
17
|
if setting_descriptor === nil
|
21
|
-
|
22
|
-
|
18
|
+
error = "Evaluating get_value('%s') failed. Value not found for key '%s'. Returning default_value: [%s]. Here are the available keys: %s" % [key, key, default_value.to_s, settings.keys.join(", ")]
|
19
|
+
@log.error(error)
|
20
|
+
return default_value, default_variation_id, nil, nil, error
|
23
21
|
end
|
24
22
|
|
25
23
|
rollout_rules = setting_descriptor.fetch(ROLLOUT_RULES, [])
|
26
24
|
rollout_percentage_items = setting_descriptor.fetch(ROLLOUT_PERCENTAGE_ITEMS, [])
|
27
25
|
|
28
26
|
if !user.equal?(nil) && !user.class.equal?(User)
|
29
|
-
|
27
|
+
@log.warn("Evaluating get_value('%s'). User Object is not an instance of User type." % key)
|
30
28
|
user = nil
|
31
29
|
end
|
32
30
|
if user === nil
|
33
31
|
if rollout_rules.size > 0 || rollout_percentage_items.size > 0
|
34
|
-
|
32
|
+
@log.warn("Evaluating get_value('%s'). UserObject missing! You should pass a UserObject to get_value(), in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/" % key)
|
35
33
|
end
|
36
34
|
return_value = setting_descriptor.fetch(VALUE, default_value)
|
37
35
|
return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
|
38
|
-
|
39
|
-
return return_value, return_variation_id
|
36
|
+
@log.info("Returning [%s]" % return_value.to_s)
|
37
|
+
return return_value, return_variation_id, nil, nil, nil
|
40
38
|
end
|
41
39
|
|
42
40
|
log_entries = ["Evaluating get_value('%s')." % key, "User object:\n%s" % user.to_s]
|
@@ -61,25 +59,25 @@ module ConfigCat
|
|
61
59
|
if comparator == 0
|
62
60
|
if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
|
63
61
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
64
|
-
return value, variation_id
|
62
|
+
return value, variation_id, rollout_rule, nil, nil
|
65
63
|
end
|
66
64
|
# IS NOT ONE OF
|
67
65
|
elsif comparator == 1
|
68
66
|
if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
|
69
67
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
70
|
-
return value, variation_id
|
68
|
+
return value, variation_id, rollout_rule, nil, nil
|
71
69
|
end
|
72
70
|
# CONTAINS
|
73
71
|
elsif comparator == 2
|
74
72
|
if user_value.to_s.include?(comparison_value.to_s)
|
75
73
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
76
|
-
return value, variation_id
|
74
|
+
return value, variation_id, rollout_rule, nil, nil
|
77
75
|
end
|
78
76
|
# DOES NOT CONTAIN
|
79
77
|
elsif comparator == 3
|
80
78
|
if !user_value.to_s.include?(comparison_value.to_s)
|
81
79
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
82
|
-
return value, variation_id
|
80
|
+
return value, variation_id, rollout_rule, nil, nil
|
83
81
|
end
|
84
82
|
# IS ONE OF, IS NOT ONE OF (Semantic version)
|
85
83
|
elsif (4 <= comparator) && (comparator <= 5)
|
@@ -92,11 +90,11 @@ module ConfigCat
|
|
92
90
|
}
|
93
91
|
if match && comparator == 4 || !match && comparator == 5
|
94
92
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
95
|
-
return value, variation_id
|
93
|
+
return value, variation_id, rollout_rule, nil, nil
|
96
94
|
end
|
97
95
|
rescue ArgumentError => e
|
98
96
|
message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
|
99
|
-
|
97
|
+
@log.warn(message)
|
100
98
|
log_entries.push(message)
|
101
99
|
next
|
102
100
|
end
|
@@ -110,11 +108,11 @@ module ConfigCat
|
|
110
108
|
(comparator == 8 && user_value_version > comparison_value_version) ||
|
111
109
|
(comparator == 9 && user_value_version >= comparison_value_version)
|
112
110
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
113
|
-
return value, variation_id
|
111
|
+
return value, variation_id, rollout_rule, nil, nil
|
114
112
|
end
|
115
113
|
rescue ArgumentError => e
|
116
114
|
message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
|
117
|
-
|
115
|
+
@log.warn(message)
|
118
116
|
log_entries.push(message)
|
119
117
|
next
|
120
118
|
end
|
@@ -129,11 +127,11 @@ module ConfigCat
|
|
129
127
|
(comparator == 14 && user_value_float > comparison_value_float) ||
|
130
128
|
(comparator == 15 && user_value_float >= comparison_value_float)
|
131
129
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
132
|
-
return value, variation_id
|
130
|
+
return value, variation_id, rollout_rule, nil, nil
|
133
131
|
end
|
134
132
|
rescue Exception => e
|
135
133
|
message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
|
136
|
-
|
134
|
+
@log.warn(message)
|
137
135
|
log_entries.push(message)
|
138
136
|
next
|
139
137
|
end
|
@@ -141,13 +139,13 @@ module ConfigCat
|
|
141
139
|
elsif comparator == 16
|
142
140
|
if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
|
143
141
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
144
|
-
return value, variation_id
|
142
|
+
return value, variation_id, rollout_rule, nil, nil
|
145
143
|
end
|
146
144
|
# IS NOT ONE OF (Sensitive)
|
147
145
|
elsif comparator == 17
|
148
146
|
if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
|
149
147
|
log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
150
|
-
return value, variation_id
|
148
|
+
return value, variation_id, rollout_rule, nil, nil
|
151
149
|
end
|
152
150
|
end
|
153
151
|
log_entries.push(format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value))
|
@@ -156,7 +154,7 @@ module ConfigCat
|
|
156
154
|
if rollout_percentage_items.size > 0
|
157
155
|
user_key = user.get_identifier()
|
158
156
|
hash_candidate = ("%s%s" % [key, user_key]).encode("utf-8")
|
159
|
-
hash_val = Digest::SHA1.hexdigest(hash_candidate)[0...7].to_i(base=16) % 100
|
157
|
+
hash_val = Digest::SHA1.hexdigest(hash_candidate)[0...7].to_i(base = 16) % 100
|
160
158
|
bucket = 0
|
161
159
|
for rollout_percentage_item in rollout_percentage_items || []
|
162
160
|
bucket += rollout_percentage_item.fetch(PERCENTAGE, 0)
|
@@ -164,34 +162,31 @@ module ConfigCat
|
|
164
162
|
percentage_value = rollout_percentage_item.fetch(VALUE, nil)
|
165
163
|
variation_id = rollout_percentage_item.fetch(VARIATION_ID, default_variation_id)
|
166
164
|
log_entries.push("Evaluating %% options. Returning %s" % percentage_value)
|
167
|
-
return percentage_value, variation_id
|
165
|
+
return percentage_value, variation_id, nil, rollout_percentage_item, nil
|
168
166
|
end
|
169
167
|
end
|
170
168
|
end
|
171
169
|
return_value = setting_descriptor.fetch(VALUE, default_value)
|
172
170
|
return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
|
173
171
|
log_entries.push("Returning %s" % return_value)
|
174
|
-
return return_value, return_variation_id
|
172
|
+
return return_value, return_variation_id, nil, nil, nil
|
175
173
|
ensure
|
176
|
-
|
174
|
+
@log.info(log_entries.join("\n"))
|
177
175
|
end
|
178
176
|
end
|
179
177
|
|
180
178
|
private
|
181
179
|
|
182
|
-
def
|
180
|
+
def format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value)
|
183
181
|
return "Evaluating rule: [%s:%s] [%s] [%s] => match, returning: %s" % [comparison_attribute, user_value, COMPARATOR_TEXTS[comparator], comparison_value, value]
|
184
182
|
end
|
185
183
|
|
186
|
-
def
|
184
|
+
def format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value)
|
187
185
|
return "Evaluating rule: [%s:%s] [%s] [%s] => no match" % [comparison_attribute, user_value, COMPARATOR_TEXTS[comparator], comparison_value]
|
188
186
|
end
|
189
187
|
|
190
|
-
def
|
188
|
+
def format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, error)
|
191
189
|
return "Evaluating rule: [%s:%s] [%s] [%s] => SKIP rule. Validation error: %s" % [comparison_attribute, user_value, COMPARATOR_TEXTS[comparator], comparison_value, error]
|
192
190
|
end
|
193
|
-
|
194
191
|
end
|
195
|
-
|
196
192
|
end
|
197
|
-
|
data/lib/configcat/user.rb
CHANGED
@@ -1,56 +1,35 @@
|
|
1
1
|
module ConfigCat
|
2
|
-
|
2
|
+
# The user object for variation evaluation
|
3
3
|
class User
|
4
|
-
#
|
5
|
-
# The user object for variation evaluation
|
6
|
-
#
|
7
|
-
|
8
4
|
PREDEFINED = ["Identifier", "Email", "Country"]
|
9
5
|
|
6
|
+
attr_reader :identifier
|
7
|
+
|
10
8
|
def initialize(identifier, email: nil, country: nil, custom: nil)
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
9
|
+
@identifier = (!identifier.equal?(nil)) ? identifier : ""
|
10
|
+
@data = { "Identifier" => identifier, "Email" => email, "Country" => country }
|
11
|
+
@custom = custom
|
14
12
|
end
|
15
13
|
|
16
|
-
def get_identifier
|
17
|
-
return @
|
14
|
+
def get_identifier
|
15
|
+
return @identifier
|
18
16
|
end
|
19
17
|
|
20
18
|
def get_attribute(attribute)
|
21
19
|
attribute = attribute.to_s
|
22
|
-
if PREDEFINED.include?(attribute)
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
if !@__custom.equal?(nil)
|
27
|
-
@__custom.each do |customField, customValue|
|
28
|
-
if customField.to_s == attribute
|
29
|
-
return customValue
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
20
|
+
return @data[attribute] if PREDEFINED.include?(attribute)
|
21
|
+
return @custom[attribute] if @custom
|
33
22
|
return nil
|
34
23
|
end
|
35
24
|
|
36
|
-
def to_s
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
if !@__custom.equal?(nil)
|
45
|
-
r += %Q(,\n "Custom": {)
|
46
|
-
for customField in @__custom
|
47
|
-
r += %Q(\n "#{customField}": "#{@__custom[customField]}",)
|
48
|
-
end
|
49
|
-
r += "\n }"
|
50
|
-
end
|
51
|
-
r += "\n}"
|
52
|
-
return r
|
25
|
+
def to_s
|
26
|
+
dump = {
|
27
|
+
'Identifier': @identifier,
|
28
|
+
'Email': @data['Email'],
|
29
|
+
'Country': @data['Country'],
|
30
|
+
'Custom': @custom,
|
31
|
+
}
|
32
|
+
return dump.to_json
|
53
33
|
end
|
54
34
|
end
|
55
|
-
|
56
35
|
end
|
data/lib/configcat/version.rb
CHANGED