qonfig 0.12.0 → 0.13.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/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
|