qonfig 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +457 -137
- data/lib/qonfig/command_set.rb +7 -1
- data/lib/qonfig/commands/add_nested_option.rb +3 -1
- data/lib/qonfig/commands/add_option.rb +2 -1
- data/lib/qonfig/commands/base.rb +2 -1
- data/lib/qonfig/commands/compose.rb +16 -10
- data/lib/qonfig/commands/expose_yaml.rb +2 -1
- data/lib/qonfig/commands/load_from_env.rb +2 -1
- data/lib/qonfig/commands/load_from_json.rb +2 -1
- data/lib/qonfig/commands/load_from_self.rb +2 -1
- data/lib/qonfig/commands/load_from_yaml.rb +2 -1
- data/lib/qonfig/data_set/lock.rb +46 -0
- data/lib/qonfig/data_set.rb +92 -23
- data/lib/qonfig/errors.rb +8 -0
- data/lib/qonfig/plugins/toml/commands/expose_toml.rb +2 -1
- data/lib/qonfig/plugins/toml/commands/load_from_toml.rb +2 -1
- data/lib/qonfig/settings/builder.rb +20 -4
- data/lib/qonfig/settings/callbacks.rb +43 -0
- data/lib/qonfig/settings/key_matcher.rb +175 -0
- data/lib/qonfig/settings/lock.rb +3 -3
- data/lib/qonfig/settings.rb +144 -33
- data/lib/qonfig/validator/basic.rb +53 -0
- data/lib/qonfig/validator/builder/attribute_consistency.rb +181 -0
- data/lib/qonfig/validator/builder.rb +169 -0
- data/lib/qonfig/validator/collection.rb +73 -0
- data/lib/qonfig/validator/dsl.rb +51 -0
- data/lib/qonfig/validator/method_based.rb +49 -0
- data/lib/qonfig/validator/predefined/common.rb +53 -0
- data/lib/qonfig/validator/predefined/registry.rb +83 -0
- data/lib/qonfig/validator/predefined/registry_control_mixin.rb +43 -0
- data/lib/qonfig/validator/predefined.rb +41 -0
- data/lib/qonfig/validator/proc_based.rb +53 -0
- data/lib/qonfig/validator.rb +58 -0
- data/lib/qonfig/version.rb +1 -1
- data/lib/qonfig.rb +1 -0
- data/qonfig.gemspec +1 -1
- metadata +19 -5
- data/lib/qonfig/data_set/validator.rb +0 -7
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.13.0
|
5
|
+
class Qonfig::Settings::KeyMatcher
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.13.0
|
10
|
+
SCOPE_SPLITTER = '.'
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.13.0
|
16
|
+
MATCHER_SCOPE_SPLITTER = '\.'
|
17
|
+
|
18
|
+
# @return [String]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.13.0
|
22
|
+
GENERIC_PART_PATTERN = '*'
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.13.0
|
28
|
+
GENERIC_REGEXP_PATTERN = '[^\.]+\.'
|
29
|
+
|
30
|
+
# @return [String]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.13.0
|
34
|
+
INFINITE_PART_PATTERN = '#'
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.13.0
|
40
|
+
INFINITE_REGEXP_PATTERN = '\.*.*'
|
41
|
+
|
42
|
+
# @param scope_pattern [String]
|
43
|
+
# @return [void]
|
44
|
+
#
|
45
|
+
# @raise [Qonfig::ArgumentError]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.13.0
|
49
|
+
def initialize(scope_pattern)
|
50
|
+
raise Qonfig::ArgumentError unless scope_pattern.is_a?(String)
|
51
|
+
|
52
|
+
@scope_pattern = scope_pattern
|
53
|
+
@scope_pattern_size = count_scope_pattern_size(scope_pattern)
|
54
|
+
@pattern_matcher = build_pattern_matcher(scope_pattern)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param setting_key_pattern [String]
|
58
|
+
# @return [Boolean]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.13.0
|
62
|
+
def match?(setting_key_pattern)
|
63
|
+
return false unless comparable_event_scopes?(setting_key_pattern)
|
64
|
+
!!pattern_matcher.match(setting_key_pattern)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# @return [Regexp]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
# @since 0.13.0
|
73
|
+
attr_reader :pattern_matcher
|
74
|
+
|
75
|
+
# @return [String]
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
# @since 0.13.0
|
79
|
+
attr_reader :scope_pattern
|
80
|
+
|
81
|
+
# @return [Integer, Float::INFINITY]
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
# @since 0.13.0
|
85
|
+
attr_reader :scope_pattern_size
|
86
|
+
|
87
|
+
# @param scope_pattern [String]
|
88
|
+
# @return [Integer, Float::INFINITY]
|
89
|
+
#
|
90
|
+
# @api private
|
91
|
+
# @since 0.13.0
|
92
|
+
def count_scope_pattern_size(scope_pattern)
|
93
|
+
return Float::INFINITY if scope_pattern == INFINITE_PART_PATTERN
|
94
|
+
return Float::INFINITY if scope_pattern.include?('.#')
|
95
|
+
return Float::INFINITY if scope_pattern.include?('#.')
|
96
|
+
return Float::INFINITY if scope_pattern.include?('.#.')
|
97
|
+
|
98
|
+
scope_pattern.split(SCOPE_SPLITTER).size
|
99
|
+
end
|
100
|
+
|
101
|
+
# @param setting_key_pattern [String]
|
102
|
+
# @return [Integer]
|
103
|
+
#
|
104
|
+
# @api private
|
105
|
+
# @since 0.13.0
|
106
|
+
def count_setting_key_pattern_size(setting_key_pattern)
|
107
|
+
setting_key_pattern.split(SCOPE_SPLITTER).size
|
108
|
+
end
|
109
|
+
|
110
|
+
# @param setting_key_pattern [String]
|
111
|
+
# @return [Boolean]
|
112
|
+
#
|
113
|
+
# @api private
|
114
|
+
# @since 0.13.0
|
115
|
+
def comparable_event_scopes?(setting_key_pattern)
|
116
|
+
# NOTE: Integer#finite?, Integer#infinite?, Float#finite?, Float#nfinite?
|
117
|
+
# Cant be used (backward compatability with old ruby versions)
|
118
|
+
return true if scope_pattern_size == Float::INFINITY
|
119
|
+
scope_pattern_size == count_setting_key_pattern_size(setting_key_pattern)
|
120
|
+
end
|
121
|
+
|
122
|
+
# @param pattern [String, NilClass]
|
123
|
+
# @return [Boolean]
|
124
|
+
#
|
125
|
+
# @api private
|
126
|
+
# @since 0.13.0
|
127
|
+
def non_generic_pattern?(pattern = nil)
|
128
|
+
return false unless pattern
|
129
|
+
pattern != GENERIC_REGEXP_PATTERN && pattern != INFINITE_REGEXP_PATTERN
|
130
|
+
end
|
131
|
+
|
132
|
+
# "\.test\.created\.today\." => "test\.created\.today"
|
133
|
+
#
|
134
|
+
# @param regexp_string [String]
|
135
|
+
# @option left [Boolean]
|
136
|
+
# @option right [Boolean]
|
137
|
+
# @return [String]
|
138
|
+
#
|
139
|
+
# @api private
|
140
|
+
# @since 0.13.0
|
141
|
+
def strip_regexp_string(regexp_string, left: false, right: false)
|
142
|
+
pattern = regexp_string
|
143
|
+
pattern = pattern[2..-1] if left && pattern[0..1] == MATCHER_SCOPE_SPLITTER
|
144
|
+
pattern = pattern[0..-3] if right && pattern[-2..-1] == MATCHER_SCOPE_SPLITTER
|
145
|
+
pattern
|
146
|
+
end
|
147
|
+
|
148
|
+
# @param scope_pattern [String]
|
149
|
+
# @return [Regexp]
|
150
|
+
#
|
151
|
+
# @api private
|
152
|
+
# @since 0.13.0
|
153
|
+
def build_pattern_matcher(scope_pattern)
|
154
|
+
routing_parts = scope_pattern.split(SCOPE_SPLITTER)
|
155
|
+
|
156
|
+
regexp_string = routing_parts.each_with_object([]) do |routing_part, regexp_parts|
|
157
|
+
case routing_part
|
158
|
+
when GENERIC_PART_PATTERN
|
159
|
+
regexp_parts << GENERIC_REGEXP_PATTERN
|
160
|
+
when INFINITE_PART_PATTERN
|
161
|
+
if non_generic_pattern?(regexp_parts.last)
|
162
|
+
regexp_parts[-1] = strip_regexp_string(regexp_parts.last, right: true)
|
163
|
+
end
|
164
|
+
|
165
|
+
regexp_parts << INFINITE_REGEXP_PATTERN
|
166
|
+
else
|
167
|
+
regexp_parts << (Regexp.escape(routing_part) + MATCHER_SCOPE_SPLITTER)
|
168
|
+
end
|
169
|
+
end.join
|
170
|
+
|
171
|
+
regexp_string = strip_regexp_string(regexp_string, left: true, right: true)
|
172
|
+
|
173
|
+
Regexp.new('\A' + regexp_string + '\z')
|
174
|
+
end
|
175
|
+
end
|
data/lib/qonfig/settings/lock.rb
CHANGED
@@ -17,7 +17,7 @@ class Qonfig::Settings::Lock
|
|
17
17
|
# @api private
|
18
18
|
# @since 0.2.0
|
19
19
|
def thread_safe_definition(&instructions)
|
20
|
-
definition_lock.synchronize(&instructions)
|
20
|
+
definition_lock.owned? ? yield : definition_lock.synchronize(&instructions)
|
21
21
|
end
|
22
22
|
|
23
23
|
# @param instructions [Proc]
|
@@ -26,7 +26,7 @@ class Qonfig::Settings::Lock
|
|
26
26
|
# @api private
|
27
27
|
# @since 0.2.0
|
28
28
|
def thread_safe_access(&instructions)
|
29
|
-
access_lock.synchronize(&instructions)
|
29
|
+
access_lock.owned? ? yield : access_lock.synchronize(&instructions)
|
30
30
|
end
|
31
31
|
|
32
32
|
# @param instructions [Proc]
|
@@ -35,7 +35,7 @@ class Qonfig::Settings::Lock
|
|
35
35
|
# @api private
|
36
36
|
# @since 0.2.0
|
37
37
|
def thread_safe_merge(&instructions)
|
38
|
-
merge_lock.synchronize(&instructions)
|
38
|
+
merge_lock.owned? ? yield : merge_lock.synchronize(&instructions)
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
data/lib/qonfig/settings.rb
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
|
-
# rubocop:disable Metrics/ClassLength
|
6
|
-
class Qonfig::Settings
|
5
|
+
# rubocop:disable Metrics/ClassLength, Layout/ClassStructure
|
6
|
+
class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_METHODS constant
|
7
|
+
require_relative 'settings/callbacks'
|
7
8
|
require_relative 'settings/lock'
|
8
9
|
require_relative 'settings/builder'
|
9
10
|
require_relative 'settings/key_guard'
|
11
|
+
require_relative 'settings/key_matcher'
|
10
12
|
|
11
13
|
# @return [Proc]
|
12
14
|
#
|
@@ -26,11 +28,49 @@ class Qonfig::Settings
|
|
26
28
|
# @since 0.1.0
|
27
29
|
attr_reader :__options__
|
28
30
|
|
31
|
+
# @return [Qonfig::Settings::Callbacks]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# @since 0.13.0
|
35
|
+
attr_reader :__mutation_callbacks__
|
36
|
+
|
29
37
|
# @api private
|
30
38
|
# @since 0.1.0
|
31
|
-
def initialize
|
39
|
+
def initialize(__mutation_callbacks__)
|
32
40
|
@__options__ = {}
|
33
41
|
@__lock__ = Lock.new
|
42
|
+
@__mutation_callbacks__ = __mutation_callbacks__
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param block [Proc]
|
46
|
+
# @return [Enumerable]
|
47
|
+
#
|
48
|
+
# @yield [key, value]
|
49
|
+
# @yieldparam key [String]
|
50
|
+
# @yieldparam value [Object]
|
51
|
+
#
|
52
|
+
# @api private
|
53
|
+
# @since 0.13.0
|
54
|
+
def __each_setting__(&block)
|
55
|
+
__lock__.thread_safe_access do
|
56
|
+
__each_key_value_pair__(&block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param initial_setting_key [String, NilClass]
|
61
|
+
# @param block [Proc]
|
62
|
+
# @return [Enumerable]
|
63
|
+
#
|
64
|
+
# @yield [key, value]
|
65
|
+
# @yieldparam key [String]
|
66
|
+
# @yieldparam value [Object]
|
67
|
+
#
|
68
|
+
# @api private
|
69
|
+
# @since 0.13.0
|
70
|
+
def __deep_each_setting__(initial_setting_key = nil, &block)
|
71
|
+
__lock__.thread_safe_access do
|
72
|
+
__deep_each_key_value_pair__(initial_setting_key, &block)
|
73
|
+
end
|
34
74
|
end
|
35
75
|
|
36
76
|
# @param key [Symbol, String]
|
@@ -39,7 +79,7 @@ class Qonfig::Settings
|
|
39
79
|
#
|
40
80
|
# @api private
|
41
81
|
# @since 0.1.0
|
42
|
-
def __define_setting__(key, value)
|
82
|
+
def __define_setting__(key, value) # rubocop:disable Metrics/AbcSize
|
43
83
|
__lock__.thread_safe_definition do
|
44
84
|
key = __indifferently_accessable_option_key__(key)
|
45
85
|
|
@@ -48,13 +88,15 @@ class Qonfig::Settings
|
|
48
88
|
case
|
49
89
|
when !__options__.key?(key)
|
50
90
|
__options__[key] = value
|
51
|
-
when __options__[key]
|
91
|
+
when __is_a_setting__(__options__[key]) && __is_a_setting__(value)
|
52
92
|
__options__[key].__append_settings__(value)
|
53
93
|
else
|
54
94
|
__options__[key] = value
|
55
95
|
end
|
56
96
|
|
57
|
-
|
97
|
+
__define_option_reader__(key)
|
98
|
+
__define_option_writer__(key)
|
99
|
+
__define_option_predicate__(key)
|
58
100
|
end
|
59
101
|
end
|
60
102
|
|
@@ -71,6 +113,14 @@ class Qonfig::Settings
|
|
71
113
|
end
|
72
114
|
end
|
73
115
|
|
116
|
+
# @return [void]
|
117
|
+
#
|
118
|
+
# @api private
|
119
|
+
# @since 0.13.0
|
120
|
+
def __invoke_mutation_callbacks__
|
121
|
+
__mutation_callbacks__.call
|
122
|
+
end
|
123
|
+
|
74
124
|
# @param key [Symbol, String]
|
75
125
|
# @return [Object]
|
76
126
|
#
|
@@ -90,13 +140,13 @@ class Qonfig::Settings
|
|
90
140
|
__lock__.thread_safe_access { __set_value__(key, value) }
|
91
141
|
end
|
92
142
|
|
93
|
-
# @param
|
143
|
+
# @param settings_map [Hash]
|
94
144
|
# @return [void]
|
95
145
|
#
|
96
146
|
# @api private
|
97
147
|
# @since 0.3.0
|
98
|
-
def __apply_values__(
|
99
|
-
__lock__.thread_safe_access { __set_values_from_map__(
|
148
|
+
def __apply_values__(settings_map)
|
149
|
+
__lock__.thread_safe_access { __set_values_from_map__(settings_map) }
|
100
150
|
end
|
101
151
|
|
102
152
|
# @param keys [Array<String, Symbol>]
|
@@ -191,7 +241,7 @@ class Qonfig::Settings
|
|
191
241
|
__options__.freeze
|
192
242
|
|
193
243
|
__options__.each_value do |value|
|
194
|
-
value.__freeze__ if value
|
244
|
+
value.__freeze__ if __is_a_setting__(value)
|
195
245
|
end
|
196
246
|
end
|
197
247
|
end
|
@@ -204,6 +254,15 @@ class Qonfig::Settings
|
|
204
254
|
__lock__.thread_safe_access { __options__.frozen? }
|
205
255
|
end
|
206
256
|
|
257
|
+
# @param value [Any]
|
258
|
+
# @return [Boolean]
|
259
|
+
#
|
260
|
+
# @api private
|
261
|
+
# @since 0.13.0
|
262
|
+
def __is_a_setting__(value)
|
263
|
+
value.is_a?(Qonfig::Settings)
|
264
|
+
end
|
265
|
+
|
207
266
|
private
|
208
267
|
|
209
268
|
# @return [Qonfig::Settings::Lock]
|
@@ -212,7 +271,47 @@ class Qonfig::Settings
|
|
212
271
|
# @since 0.2.0
|
213
272
|
attr_reader :__lock__
|
214
273
|
|
215
|
-
# @param
|
274
|
+
# @param block [Proc]
|
275
|
+
# @return [Enumerable]
|
276
|
+
#
|
277
|
+
# @yield [setting_key, setting_value]
|
278
|
+
# @yieldparam key [String]
|
279
|
+
# @yieldparam value [Object]
|
280
|
+
#
|
281
|
+
# @api private
|
282
|
+
# @since 0.13.0
|
283
|
+
def __each_key_value_pair__(&block)
|
284
|
+
__options__.each_pair(&block)
|
285
|
+
end
|
286
|
+
|
287
|
+
# @param initial_setting_key [String, NilClass]
|
288
|
+
# @param block [Proc]
|
289
|
+
# @return [Enumerable]
|
290
|
+
#
|
291
|
+
# @yield [setting_key, setting_value]
|
292
|
+
# @yieldparam setting_key [String]
|
293
|
+
# @yieldparam setting_value [Object]
|
294
|
+
#
|
295
|
+
# @api private
|
296
|
+
# @since 0.13.0
|
297
|
+
def __deep_each_key_value_pair__(initial_setting_key = nil, &block)
|
298
|
+
enumerator = Enumerator.new do |yielder|
|
299
|
+
__each_key_value_pair__ do |setting_key, setting_value|
|
300
|
+
final_setting_key =
|
301
|
+
initial_setting_key ? "#{initial_setting_key}.#{setting_key}" : setting_key
|
302
|
+
|
303
|
+
if __is_a_setting__(setting_value)
|
304
|
+
setting_value.__deep_each_setting__(final_setting_key, &block)
|
305
|
+
else
|
306
|
+
yielder.yield(final_setting_key, setting_value)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
block_given? ? enumerator.each(&block) : enumerator
|
312
|
+
end
|
313
|
+
|
314
|
+
# @param settings_map [Hash]
|
216
315
|
# @return [void]
|
217
316
|
#
|
218
317
|
# @raise [Qonfig::ArgumentError]
|
@@ -220,21 +319,21 @@ class Qonfig::Settings
|
|
220
319
|
#
|
221
320
|
# @api private
|
222
321
|
# @since 0.3.0
|
223
|
-
def __set_values_from_map__(
|
322
|
+
def __set_values_from_map__(settings_map)
|
224
323
|
::Kernel.raise(
|
225
324
|
Qonfig::ArgumentError, 'Options map should be represented as a hash'
|
226
|
-
) unless
|
325
|
+
) unless settings_map.is_a?(Hash)
|
227
326
|
|
228
|
-
|
327
|
+
settings_map.each_pair do |key, value|
|
229
328
|
current_value = __get_value__(key)
|
230
329
|
|
231
330
|
# NOTE: some duplications here was made only for the better code readability
|
232
331
|
case
|
233
|
-
when !current_value
|
332
|
+
when !__is_a_setting__(current_value)
|
234
333
|
__set_value__(key, value)
|
235
|
-
when current_value
|
334
|
+
when __is_a_setting__(current_value) && value.is_a?(Hash)
|
236
335
|
current_value.__apply_values__(value)
|
237
|
-
when current_value
|
336
|
+
when __is_a_setting__(current_value) && !value.is_a?(Hash)
|
238
337
|
::Kernel.raise(
|
239
338
|
Qonfig::AmbiguousSettingValueError,
|
240
339
|
"Can not redefine option <#{key}> that contains nested options"
|
@@ -255,12 +354,10 @@ class Qonfig::Settings
|
|
255
354
|
) if __options__.frozen?
|
256
355
|
|
257
356
|
__options__.each_pair do |key, value|
|
258
|
-
|
259
|
-
value.__clear__
|
260
|
-
else
|
261
|
-
__options__[key] = nil
|
262
|
-
end
|
357
|
+
__is_a_setting__(value) ? value.__clear__ : __options__[key] = nil
|
263
358
|
end
|
359
|
+
|
360
|
+
__invoke_mutation_callbacks__
|
264
361
|
end
|
265
362
|
|
266
363
|
# @param key [String, Symbol]
|
@@ -301,14 +398,16 @@ class Qonfig::Settings
|
|
301
398
|
::Kernel.raise(Qonfig::FrozenSettingsError, 'Can not modify frozen settings')
|
302
399
|
end
|
303
400
|
|
304
|
-
if __options__[key]
|
401
|
+
if __is_a_setting__(__options__[key])
|
305
402
|
::Kernel.raise(
|
306
403
|
Qonfig::AmbiguousSettingValueError,
|
307
404
|
"Can not redefine option <#{key}> that contains nested options"
|
308
405
|
)
|
309
406
|
end
|
310
407
|
|
311
|
-
__options__[key] = value
|
408
|
+
(__options__[key] = value)
|
409
|
+
|
410
|
+
__invoke_mutation_callbacks__
|
312
411
|
end
|
313
412
|
|
314
413
|
# @param keys [Array<Symbol, String>]
|
@@ -328,12 +427,12 @@ class Qonfig::Settings
|
|
328
427
|
case
|
329
428
|
when rest_keys.empty?
|
330
429
|
result
|
331
|
-
when !result
|
430
|
+
when !__is_a_setting__(result)
|
332
431
|
::Kernel.raise(
|
333
432
|
Qonfig::UnknownSettingError,
|
334
433
|
'Setting with required digging sequence does not exist!'
|
335
434
|
)
|
336
|
-
when result
|
435
|
+
when __is_a_setting__(result)
|
337
436
|
result.__dig__(*rest_keys)
|
338
437
|
end
|
339
438
|
end
|
@@ -350,7 +449,7 @@ class Qonfig::Settings
|
|
350
449
|
{}.tap do |result|
|
351
450
|
__deep_access__(*keys).tap do |setting|
|
352
451
|
required_key = __indifferently_accessable_option_key__(keys.last)
|
353
|
-
result[required_key] = setting
|
452
|
+
result[required_key] = __is_a_setting__(setting) ? setting.__to_h__ : setting
|
354
453
|
end
|
355
454
|
end
|
356
455
|
end
|
@@ -386,7 +485,7 @@ class Qonfig::Settings
|
|
386
485
|
transform_key: transform_key,
|
387
486
|
transform_value: transform_value
|
388
487
|
)
|
389
|
-
when value
|
488
|
+
when __is_a_setting__(value)
|
390
489
|
hash[final_key] = value.__to_hash__(
|
391
490
|
transform_key: transform_key,
|
392
491
|
transform_value: transform_value
|
@@ -402,16 +501,30 @@ class Qonfig::Settings
|
|
402
501
|
# @return [void]
|
403
502
|
#
|
404
503
|
# @api private
|
405
|
-
# @since 0.
|
406
|
-
def
|
504
|
+
# @since 0.13.0
|
505
|
+
def __define_option_reader__(key)
|
407
506
|
define_singleton_method(key) do
|
408
507
|
self.[](key)
|
409
508
|
end
|
509
|
+
end
|
410
510
|
|
511
|
+
# @param key [Symbol, String]
|
512
|
+
# @return [void]
|
513
|
+
#
|
514
|
+
# @api private
|
515
|
+
# @since 0.13.0
|
516
|
+
def __define_option_writer__(key)
|
411
517
|
define_singleton_method("#{key}=") do |value|
|
412
518
|
self.[]=(key, value)
|
413
519
|
end
|
520
|
+
end
|
414
521
|
|
522
|
+
# @param key [Symbol, String]
|
523
|
+
# @return [void]
|
524
|
+
#
|
525
|
+
# @api private
|
526
|
+
# @since 0.13.0
|
527
|
+
def __define_option_predicate__(key)
|
415
528
|
define_singleton_method("#{key}?") do
|
416
529
|
!!self.[](key)
|
417
530
|
end
|
@@ -442,7 +555,6 @@ class Qonfig::Settings
|
|
442
555
|
KeyGuard.new(key).prevent_core_method_intersection!
|
443
556
|
end
|
444
557
|
|
445
|
-
# rubocop:disable Layout/ClassStructure
|
446
558
|
# @return [Array<String>]
|
447
559
|
#
|
448
560
|
# @api private
|
@@ -452,6 +564,5 @@ class Qonfig::Settings
|
|
452
564
|
private_instance_methods(false) |
|
453
565
|
%i[super define_singleton_method self]
|
454
566
|
).map(&:to_s).freeze
|
455
|
-
# rubocop:enable Layout/ClassStructure
|
456
567
|
end
|
457
|
-
# rubocop:enable Metrics/ClassLength
|
568
|
+
# rubocop:enable Metrics/ClassLength, Layout/ClassStructure
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.13.0
|
5
|
+
class Qonfig::Validator::Basic
|
6
|
+
# @return [String, Symbol, NilClass]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.13.0
|
10
|
+
attr_reader :setting_key_matcher
|
11
|
+
|
12
|
+
# @param setting_key_matcher [Qonfig::Settings::KeyMatcher, NilClass]
|
13
|
+
# @return [void]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
# @since 0.13.0
|
17
|
+
def initialize(setting_key_matcher)
|
18
|
+
@setting_key_matcher = setting_key_matcher
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param data_set [Qonfig::DataSet]
|
22
|
+
# @return [Boolean]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
# @since 0.13.0
|
26
|
+
def validate(data_set)
|
27
|
+
setting_key_provided? ? validate_concrete(data_set) : validate_full(data_set)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# @return [Boolean]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.13.0
|
36
|
+
def setting_key_provided?
|
37
|
+
!setting_key_matcher.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param data_set [Qonfig::DataSet]
|
41
|
+
# @return [Any]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
# @since 0.13.0
|
45
|
+
def validate_full(data_set); end
|
46
|
+
|
47
|
+
# @param data_set [Qonfig::DataSet]
|
48
|
+
# @return [Any]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
# @since 0.13.0
|
52
|
+
def validate_concrete(data_set); end
|
53
|
+
end
|