qonfig 0.10.0 → 0.11.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/.gitignore +1 -0
- data/.rspec +1 -1
- data/.rubocop.yml +1 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +10 -0
- data/README.md +146 -1
- data/Rakefile +2 -0
- data/lib/qonfig/command_set.rb +53 -55
- data/lib/qonfig/commands/add_nested_option.rb +36 -40
- data/lib/qonfig/commands/add_option.rb +33 -37
- data/lib/qonfig/commands/base.rb +9 -13
- data/lib/qonfig/commands/compose.rb +29 -33
- data/lib/qonfig/commands/expose_yaml.rb +154 -158
- data/lib/qonfig/commands/load_from_env.rb +77 -79
- data/lib/qonfig/commands/load_from_json.rb +52 -56
- data/lib/qonfig/commands/load_from_self.rb +57 -61
- data/lib/qonfig/commands/load_from_yaml.rb +54 -58
- data/lib/qonfig/commands.rb +15 -0
- data/lib/qonfig/configurable.rb +88 -90
- data/lib/qonfig/data_set/class_builder.rb +17 -21
- data/lib/qonfig/data_set.rb +186 -138
- data/lib/qonfig/dsl.rb +106 -108
- data/lib/qonfig/{error.rb → exceptions.rb} +13 -1
- data/lib/qonfig/loaders/basic.rb +30 -32
- data/lib/qonfig/loaders/json.rb +16 -23
- data/lib/qonfig/loaders/yaml.rb +16 -23
- data/lib/qonfig/loaders.rb +9 -0
- data/lib/qonfig/plugins/abstract.rb +7 -11
- data/lib/qonfig/plugins/access_mixin.rb +21 -25
- data/lib/qonfig/plugins/registry.rb +120 -124
- data/lib/qonfig/plugins.rb +56 -54
- data/lib/qonfig/settings/builder.rb +10 -14
- data/lib/qonfig/settings/key_guard.rb +60 -64
- data/lib/qonfig/settings/lock.rb +53 -57
- data/lib/qonfig/settings.rb +392 -354
- data/lib/qonfig/uploaders/base.rb +18 -0
- data/lib/qonfig/uploaders/file.rb +55 -0
- data/lib/qonfig/uploaders/json.rb +35 -0
- data/lib/qonfig/uploaders/yaml.rb +93 -0
- data/lib/qonfig/uploaders.rb +10 -0
- data/lib/qonfig/version.rb +1 -1
- data/lib/qonfig.rb +4 -21
- data/qonfig.gemspec +1 -1
- metadata +13 -6
data/lib/qonfig/settings.rb
CHANGED
@@ -1,419 +1,457 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
# rubocop:disable Metrics/ClassLength
|
6
|
+
class Qonfig::Settings
|
7
|
+
require_relative 'settings/lock'
|
8
|
+
require_relative 'settings/builder'
|
9
|
+
require_relative 'settings/key_guard'
|
10
|
+
|
11
|
+
# @return [Proc]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.11.0
|
15
|
+
BASIC_SETTING_KEY_TRANSFORMER = (proc { |value| value }).freeze
|
16
|
+
|
17
|
+
# @return [Proc]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
# @since 0.11.0
|
21
|
+
BASIC_SETTING_VALUE_TRANSFORMER = (proc { |value| value }).freeze
|
5
22
|
|
23
|
+
# @return [Hash]
|
24
|
+
#
|
6
25
|
# @api private
|
7
26
|
# @since 0.1.0
|
8
|
-
|
9
|
-
# @return [Hash]
|
10
|
-
#
|
11
|
-
# @api private
|
12
|
-
# @since 0.1.0
|
13
|
-
attr_reader :__options__
|
14
|
-
|
15
|
-
# @api private
|
16
|
-
# @since 0.1.0
|
17
|
-
def initialize
|
18
|
-
@__options__ = {}
|
19
|
-
@__lock__ = Lock.new
|
20
|
-
end
|
27
|
+
attr_reader :__options__
|
21
28
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
__options__[key] = value
|
41
|
-
end
|
42
|
-
|
43
|
-
__define_accessor__(key)
|
44
|
-
end
|
45
|
-
end
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
def initialize
|
32
|
+
@__options__ = {}
|
33
|
+
@__lock__ = Lock.new
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param key [Symbol, String]
|
37
|
+
# @param value [Object]
|
38
|
+
# @return [void]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
def __define_setting__(key, value)
|
43
|
+
__lock__.thread_safe_definition do
|
44
|
+
key = __indifferently_accessable_option_key__(key)
|
45
|
+
|
46
|
+
__prevent_core_method_intersection__(key)
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
settings.__options__.each_pair do |key, value|
|
55
|
-
__define_setting__(key, value)
|
56
|
-
end
|
48
|
+
case
|
49
|
+
when !__options__.key?(key)
|
50
|
+
__options__[key] = value
|
51
|
+
when __options__[key].is_a?(Qonfig::Settings) && value.is_a?(Qonfig::Settings)
|
52
|
+
__options__[key].__append_settings__(value)
|
53
|
+
else
|
54
|
+
__options__[key] = value
|
57
55
|
end
|
58
|
-
end
|
59
56
|
|
60
|
-
|
61
|
-
# @return [Object]
|
62
|
-
#
|
63
|
-
# @api public
|
64
|
-
# @since 0.1.0
|
65
|
-
def [](key)
|
66
|
-
__lock__.thread_safe_access { __get_value__(key) }
|
57
|
+
__define_accessor__(key)
|
67
58
|
end
|
59
|
+
end
|
68
60
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
61
|
+
# @param settings [Qonfig::Settings]
|
62
|
+
# @return [void]
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
# @since 0.1.0
|
66
|
+
def __append_settings__(settings)
|
67
|
+
__lock__.thread_safe_merge do
|
68
|
+
settings.__options__.each_pair do |key, value|
|
69
|
+
__define_setting__(key, value)
|
70
|
+
end
|
77
71
|
end
|
72
|
+
end
|
78
73
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
74
|
+
# @param key [Symbol, String]
|
75
|
+
# @return [Object]
|
76
|
+
#
|
77
|
+
# @api public
|
78
|
+
# @since 0.1.0
|
79
|
+
def [](key)
|
80
|
+
__lock__.thread_safe_access { __get_value__(key) }
|
81
|
+
end
|
87
82
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
83
|
+
# @param key [String, Symbol]
|
84
|
+
# @param value [Object]
|
85
|
+
# @return [void]
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
# @since 0.1.0
|
89
|
+
def []=(key, value)
|
90
|
+
__lock__.thread_safe_access { __set_value__(key, value) }
|
91
|
+
end
|
96
92
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
93
|
+
# @param options_map [Hash]
|
94
|
+
# @return [void]
|
95
|
+
#
|
96
|
+
# @api private
|
97
|
+
# @since 0.3.0
|
98
|
+
def __apply_values__(options_map)
|
99
|
+
__lock__.thread_safe_access { __set_values_from_map__(options_map) }
|
100
|
+
end
|
105
101
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
102
|
+
# @param keys [Array<String, Symbol>]
|
103
|
+
# @return [Object]
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
# @since 0.2.0
|
107
|
+
def __dig__(*keys)
|
108
|
+
__lock__.thread_safe_access { __deep_access__(*keys) }
|
109
|
+
end
|
114
110
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
# @return [void]
|
125
|
-
#
|
126
|
-
# @api private
|
127
|
-
# @since 0.2.0
|
128
|
-
def __clear__
|
129
|
-
__lock__.thread_safe_access { __clear_option_values__ }
|
130
|
-
end
|
111
|
+
# @param keys [Array<String, Symbol>]
|
112
|
+
# @return [Hash]
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @since 0.9.0
|
116
|
+
def __slice__(*keys)
|
117
|
+
__lock__.thread_safe_access { __deep_slice__(*keys) }
|
118
|
+
end
|
131
119
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# @since 0.1.0
|
141
|
-
def method_missing(method_name, *arguments, &block)
|
142
|
-
super
|
143
|
-
rescue NoMethodError
|
144
|
-
::Kernel.raise(Qonfig::UnknownSettingError, "Setting with <#{method_name}> key doesnt exist!")
|
145
|
-
end
|
120
|
+
# @param keys [Array<String, Symbol>]
|
121
|
+
# @return [Hash, Any]
|
122
|
+
#
|
123
|
+
# @api private
|
124
|
+
# @since 0.10.0
|
125
|
+
def __slice_value__(*keys)
|
126
|
+
__lock__.thread_safe_access { __deep_slice_value__(*keys) }
|
127
|
+
end
|
146
128
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
129
|
+
# @option transform_key [Proc]
|
130
|
+
# @option transform_value [Proc]
|
131
|
+
# @return [Hash]
|
132
|
+
#
|
133
|
+
# @api private
|
134
|
+
# @since 0.1.0
|
135
|
+
# rubocop:disable Metrics/LineLength
|
136
|
+
def __to_hash__(transform_key: BASIC_SETTING_KEY_TRANSFORMER, transform_value: BASIC_SETTING_VALUE_TRANSFORMER)
|
137
|
+
unless transform_key.is_a?(Proc)
|
138
|
+
::Kernel.raise(Qonfig::IncorrectKeyTransformerError, 'Key transformer should be a proc')
|
155
139
|
end
|
156
140
|
|
157
|
-
|
158
|
-
|
159
|
-
# @api private
|
160
|
-
# @since 0.1.0
|
161
|
-
def __freeze__
|
162
|
-
__lock__.thread_safe_access do
|
163
|
-
__options__.freeze
|
164
|
-
|
165
|
-
__options__.each_value do |value|
|
166
|
-
value.__freeze__ if value.is_a?(Qonfig::Settings)
|
167
|
-
end
|
168
|
-
end
|
141
|
+
unless transform_value.is_a?(Proc)
|
142
|
+
::Kernel.raise(Qonfig::IncorrectValueTransformerError, 'Value transformer should be a proc')
|
169
143
|
end
|
170
144
|
|
171
|
-
|
172
|
-
|
173
|
-
# @api private
|
174
|
-
# @since 0.2.0
|
175
|
-
def __is_frozen__
|
176
|
-
__lock__.thread_safe_access { __options__.frozen? }
|
145
|
+
__lock__.thread_safe_access do
|
146
|
+
__build_hash_representation__(transform_key: transform_key, transform_value: transform_value)
|
177
147
|
end
|
148
|
+
end
|
149
|
+
# rubocop:enable Metrics/LineLength
|
150
|
+
alias_method :__to_h__, :__to_hash__
|
178
151
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
# @param options_map [Hash]
|
188
|
-
# @return [void]
|
189
|
-
#
|
190
|
-
# @raise [Qonfig::ArgumentError]
|
191
|
-
# @raise [Qonfig::AmbiguousSettingValueError]
|
192
|
-
#
|
193
|
-
# @api private
|
194
|
-
# @since 0.3.0
|
195
|
-
def __set_values_from_map__(options_map)
|
196
|
-
::Kernel.raise(
|
197
|
-
Qonfig::ArgumentError, 'Options map should be represented as a hash'
|
198
|
-
) unless options_map.is_a?(Hash)
|
199
|
-
|
200
|
-
options_map.each_pair do |key, value|
|
201
|
-
current_value = __get_value__(key)
|
202
|
-
|
203
|
-
# NOTE: some duplications here was made only for the better code readability
|
204
|
-
case
|
205
|
-
when !current_value.is_a?(Qonfig::Settings)
|
206
|
-
__set_value__(key, value)
|
207
|
-
when current_value.is_a?(Qonfig::Settings) && value.is_a?(Hash)
|
208
|
-
current_value.__apply_values__(value)
|
209
|
-
when current_value.is_a?(Qonfig::Settings) && !value.is_a?(Hash)
|
210
|
-
::Kernel.raise(
|
211
|
-
Qonfig::AmbiguousSettingValueError,
|
212
|
-
"Can not redefine option <#{key}> that contains nested options"
|
213
|
-
)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
152
|
+
# @return [void]
|
153
|
+
#
|
154
|
+
# @api private
|
155
|
+
# @since 0.2.0
|
156
|
+
def __clear__
|
157
|
+
__lock__.thread_safe_access { __clear_option_values__ }
|
158
|
+
end
|
217
159
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
else
|
233
|
-
__options__[key] = nil
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
160
|
+
# @param method_name [String, Symbol]
|
161
|
+
# @param arguments [Array<Object>]
|
162
|
+
# @param block [Proc]
|
163
|
+
# @return [void]
|
164
|
+
#
|
165
|
+
# @raise [Qonfig::UnknownSettingError]
|
166
|
+
#
|
167
|
+
# @api private
|
168
|
+
# @since 0.1.0
|
169
|
+
def method_missing(method_name, *arguments, &block)
|
170
|
+
super
|
171
|
+
rescue NoMethodError
|
172
|
+
::Kernel.raise(Qonfig::UnknownSettingError, "Setting with <#{method_name}> key doesnt exist!")
|
173
|
+
end
|
237
174
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
#
|
244
|
-
|
245
|
-
|
246
|
-
|
175
|
+
# @return [Boolean]
|
176
|
+
#
|
177
|
+
# @api private
|
178
|
+
# @since 0.1.0
|
179
|
+
def respond_to_missing?(method_name, include_private = false)
|
180
|
+
# :nocov:
|
181
|
+
__options__.key?(method_name.to_s) || __options__.key?(method_name.to_sym) || super
|
182
|
+
# :nocov:
|
183
|
+
end
|
247
184
|
|
248
|
-
|
249
|
-
|
250
|
-
|
185
|
+
# @return [void]
|
186
|
+
#
|
187
|
+
# @api private
|
188
|
+
# @since 0.1.0
|
189
|
+
def __freeze__
|
190
|
+
__lock__.thread_safe_access do
|
191
|
+
__options__.freeze
|
251
192
|
|
252
|
-
__options__
|
193
|
+
__options__.each_value do |value|
|
194
|
+
value.__freeze__ if value.is_a?(Qonfig::Settings)
|
195
|
+
end
|
253
196
|
end
|
197
|
+
end
|
254
198
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
#
|
263
|
-
# @api private
|
264
|
-
# @since 0.2.0
|
265
|
-
def __set_value__(key, value)
|
266
|
-
key = __indifferently_accessable_option_key__(key)
|
199
|
+
# @return [Boolean]
|
200
|
+
#
|
201
|
+
# @api private
|
202
|
+
# @since 0.2.0
|
203
|
+
def __is_frozen__
|
204
|
+
__lock__.thread_safe_access { __options__.frozen? }
|
205
|
+
end
|
267
206
|
|
268
|
-
|
269
|
-
::Kernel.raise(Qonfig::UnknownSettingError, "Setting with <#{key}> key does not exist!")
|
270
|
-
end
|
207
|
+
private
|
271
208
|
|
272
|
-
|
273
|
-
|
274
|
-
|
209
|
+
# @return [Qonfig::Settings::Lock]
|
210
|
+
#
|
211
|
+
# @api private
|
212
|
+
# @since 0.2.0
|
213
|
+
attr_reader :__lock__
|
214
|
+
|
215
|
+
# @param options_map [Hash]
|
216
|
+
# @return [void]
|
217
|
+
#
|
218
|
+
# @raise [Qonfig::ArgumentError]
|
219
|
+
# @raise [Qonfig::AmbiguousSettingValueError]
|
220
|
+
#
|
221
|
+
# @api private
|
222
|
+
# @since 0.3.0
|
223
|
+
def __set_values_from_map__(options_map)
|
224
|
+
::Kernel.raise(
|
225
|
+
Qonfig::ArgumentError, 'Options map should be represented as a hash'
|
226
|
+
) unless options_map.is_a?(Hash)
|
275
227
|
|
276
|
-
|
228
|
+
options_map.each_pair do |key, value|
|
229
|
+
current_value = __get_value__(key)
|
230
|
+
|
231
|
+
# NOTE: some duplications here was made only for the better code readability
|
232
|
+
case
|
233
|
+
when !current_value.is_a?(Qonfig::Settings)
|
234
|
+
__set_value__(key, value)
|
235
|
+
when current_value.is_a?(Qonfig::Settings) && value.is_a?(Hash)
|
236
|
+
current_value.__apply_values__(value)
|
237
|
+
when current_value.is_a?(Qonfig::Settings) && !value.is_a?(Hash)
|
277
238
|
::Kernel.raise(
|
278
239
|
Qonfig::AmbiguousSettingValueError,
|
279
240
|
"Can not redefine option <#{key}> that contains nested options"
|
280
241
|
)
|
281
242
|
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# @return [void]
|
247
|
+
#
|
248
|
+
# @raise [Qonfig::FrozenSettingsError]
|
249
|
+
#
|
250
|
+
# @api private
|
251
|
+
# @since 0.2.0
|
252
|
+
def __clear_option_values__
|
253
|
+
::Kernel.raise(
|
254
|
+
Qonfig::FrozenSettingsError, 'Can not modify frozen settings'
|
255
|
+
) if __options__.frozen?
|
256
|
+
|
257
|
+
__options__.each_pair do |key, value|
|
258
|
+
if value.is_a?(Qonfig::Settings)
|
259
|
+
value.__clear__
|
260
|
+
else
|
261
|
+
__options__[key] = nil
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
282
265
|
|
283
|
-
|
266
|
+
# @param key [String, Symbol]
|
267
|
+
# @return [Object]
|
268
|
+
#
|
269
|
+
# @raise [Qonfig::UnknownSettingError]
|
270
|
+
#
|
271
|
+
# @api private
|
272
|
+
# @since 0.2.0
|
273
|
+
def __get_value__(key)
|
274
|
+
key = __indifferently_accessable_option_key__(key)
|
275
|
+
|
276
|
+
unless __options__.key?(key)
|
277
|
+
::Kernel.raise(Qonfig::UnknownSettingError, "Setting with <#{key}> key does not exist!")
|
284
278
|
end
|
285
279
|
|
286
|
-
|
287
|
-
|
288
|
-
#
|
289
|
-
# @raise [Qonfig::ArgumentError]
|
290
|
-
# @raise [Qonfig::UnknownSettingError]
|
291
|
-
#
|
292
|
-
# @api private
|
293
|
-
# @since 0.2.0
|
294
|
-
def __deep_access__(*keys)
|
295
|
-
::Kernel.raise(Qonfig::ArgumentError, 'Key list can not be empty') if keys.empty?
|
280
|
+
__options__[key]
|
281
|
+
end
|
296
282
|
|
297
|
-
|
298
|
-
|
283
|
+
# @param key [String, Symbol]
|
284
|
+
# @param value [Object]
|
285
|
+
# @return [void]
|
286
|
+
#
|
287
|
+
# @raise [Qonfig::UnknownSettingError]
|
288
|
+
# @raise [Qonfig::FrozenSettingsError]
|
289
|
+
# @raise [Qonfig::AmbiguousSettingValueError]
|
290
|
+
#
|
291
|
+
# @api private
|
292
|
+
# @since 0.2.0
|
293
|
+
def __set_value__(key, value)
|
294
|
+
key = __indifferently_accessable_option_key__(key)
|
299
295
|
|
300
|
-
|
301
|
-
|
302
|
-
result
|
303
|
-
when !result.is_a?(Qonfig::Settings)
|
304
|
-
::Kernel.raise(
|
305
|
-
Qonfig::UnknownSettingError,
|
306
|
-
'Setting with required digging sequence does not exist!'
|
307
|
-
)
|
308
|
-
when result.is_a?(Qonfig::Settings)
|
309
|
-
result.__dig__(*rest_keys)
|
310
|
-
end
|
296
|
+
unless __options__.key?(key)
|
297
|
+
::Kernel.raise(Qonfig::UnknownSettingError, "Setting with <#{key}> key does not exist!")
|
311
298
|
end
|
312
299
|
|
313
|
-
|
314
|
-
|
315
|
-
#
|
316
|
-
# @raise [Qonfig::ArgumentError]
|
317
|
-
# @raise [Qonfig::UnknownSettingError]
|
318
|
-
#
|
319
|
-
# @api private
|
320
|
-
# @since 0.9.0
|
321
|
-
def __deep_slice__(*keys)
|
322
|
-
{}.tap do |result|
|
323
|
-
__deep_access__(*keys).tap do |setting|
|
324
|
-
required_key = __indifferently_accessable_option_key__(keys.last)
|
325
|
-
result[required_key] = setting.is_a?(Qonfig::Settings) ? setting.__to_h__ : setting
|
326
|
-
end
|
327
|
-
end
|
300
|
+
if __options__.frozen?
|
301
|
+
::Kernel.raise(Qonfig::FrozenSettingsError, 'Can not modify frozen settings')
|
328
302
|
end
|
329
303
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
#
|
336
|
-
# @api private
|
337
|
-
# @since 0.1.0
|
338
|
-
def __deep_slice_value__(*keys)
|
339
|
-
required_key = __indifferently_accessable_option_key__(keys.last)
|
340
|
-
__deep_slice__(*keys)[required_key]
|
304
|
+
if __options__[key].is_a?(Qonfig::Settings)
|
305
|
+
::Kernel.raise(
|
306
|
+
Qonfig::AmbiguousSettingValueError,
|
307
|
+
"Can not redefine option <#{key}> that contains nested options"
|
308
|
+
)
|
341
309
|
end
|
342
310
|
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
311
|
+
__options__[key] = value
|
312
|
+
end
|
313
|
+
|
314
|
+
# @param keys [Array<Symbol, String>]
|
315
|
+
# @return [Object]
|
316
|
+
#
|
317
|
+
# @raise [Qonfig::ArgumentError]
|
318
|
+
# @raise [Qonfig::UnknownSettingError]
|
319
|
+
#
|
320
|
+
# @api private
|
321
|
+
# @since 0.2.0
|
322
|
+
def __deep_access__(*keys)
|
323
|
+
::Kernel.raise(Qonfig::ArgumentError, 'Key list can not be empty') if keys.empty?
|
324
|
+
|
325
|
+
result = __get_value__(keys.first)
|
326
|
+
rest_keys = Array(keys[1..-1])
|
327
|
+
|
328
|
+
case
|
329
|
+
when rest_keys.empty?
|
330
|
+
result
|
331
|
+
when !result.is_a?(Qonfig::Settings)
|
332
|
+
::Kernel.raise(
|
333
|
+
Qonfig::UnknownSettingError,
|
334
|
+
'Setting with required digging sequence does not exist!'
|
335
|
+
)
|
336
|
+
when result.is_a?(Qonfig::Settings)
|
337
|
+
result.__dig__(*rest_keys)
|
359
338
|
end
|
339
|
+
end
|
360
340
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
341
|
+
# @param keys [Array<Symbol, String>]
|
342
|
+
# @return [Hash]
|
343
|
+
#
|
344
|
+
# @raise [Qonfig::ArgumentError]
|
345
|
+
# @raise [Qonfig::UnknownSettingError]
|
346
|
+
#
|
347
|
+
# @api private
|
348
|
+
# @since 0.9.0
|
349
|
+
def __deep_slice__(*keys)
|
350
|
+
{}.tap do |result|
|
351
|
+
__deep_access__(*keys).tap do |setting|
|
352
|
+
required_key = __indifferently_accessable_option_key__(keys.last)
|
353
|
+
result[required_key] = setting.is_a?(Qonfig::Settings) ? setting.__to_h__ : setting
|
369
354
|
end
|
355
|
+
end
|
356
|
+
end
|
370
357
|
|
371
|
-
|
372
|
-
|
373
|
-
|
358
|
+
# @param keys [Array<Symbol, String>]
|
359
|
+
# @return [Hash]
|
360
|
+
#
|
361
|
+
# @raise [Qonfig::ArgumentError]
|
362
|
+
# @raise [Qonfig::UnknownSettingError]
|
363
|
+
#
|
364
|
+
# @api private
|
365
|
+
# @since 0.1.0
|
366
|
+
def __deep_slice_value__(*keys)
|
367
|
+
required_key = __indifferently_accessable_option_key__(keys.last)
|
368
|
+
__deep_slice__(*keys)[required_key]
|
369
|
+
end
|
370
|
+
|
371
|
+
# @param options_part [Hash]
|
372
|
+
# @option transform_key [Proc]
|
373
|
+
# @option transform_value [Proc]
|
374
|
+
# @return [Hash]
|
375
|
+
#
|
376
|
+
# @api private
|
377
|
+
# @since 0.2.0
|
378
|
+
def __build_hash_representation__(options_part = __options__, transform_key:, transform_value:)
|
379
|
+
options_part.each_with_object({}) do |(key, value), hash|
|
380
|
+
final_key = transform_key.call(key)
|
374
381
|
|
375
|
-
|
376
|
-
|
382
|
+
case
|
383
|
+
when value.is_a?(Hash)
|
384
|
+
hash[final_key] = __build_hash_representation__(
|
385
|
+
value,
|
386
|
+
transform_key: transform_key,
|
387
|
+
transform_value: transform_value
|
388
|
+
)
|
389
|
+
when value.is_a?(Qonfig::Settings)
|
390
|
+
hash[final_key] = value.__to_hash__(
|
391
|
+
transform_key: transform_key,
|
392
|
+
transform_value: transform_value
|
393
|
+
)
|
394
|
+
else
|
395
|
+
final_value = transform_value.call(value)
|
396
|
+
hash[final_key] = final_value
|
377
397
|
end
|
378
398
|
end
|
399
|
+
end
|
379
400
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
def __indifferently_accessable_option_key__(key)
|
389
|
-
KeyGuard.new(key).prevent_incompatible_key_type!
|
390
|
-
key.to_s
|
401
|
+
# @param key [Symbol, String]
|
402
|
+
# @return [void]
|
403
|
+
#
|
404
|
+
# @api private
|
405
|
+
# @since 0.1.0
|
406
|
+
def __define_accessor__(key)
|
407
|
+
define_singleton_method(key) do
|
408
|
+
self.[](key)
|
391
409
|
end
|
392
410
|
|
393
|
-
#
|
394
|
-
|
395
|
-
#
|
396
|
-
# @raise [Qonfig::CoreMethodIntersectionError]
|
397
|
-
# @see Qonfig::Settings::KeyGuard
|
398
|
-
#
|
399
|
-
# @api private
|
400
|
-
# @since 0.2.0
|
401
|
-
def __prevent_core_method_intersection__(key)
|
402
|
-
KeyGuard.new(key).prevent_core_method_intersection!
|
411
|
+
define_singleton_method("#{key}=") do |value|
|
412
|
+
self.[]=(key, value)
|
403
413
|
end
|
404
414
|
|
405
|
-
#
|
406
|
-
|
407
|
-
|
408
|
-
# @api private
|
409
|
-
# @since 0.2.0
|
410
|
-
CORE_METHODS = Array(
|
411
|
-
instance_methods(false) |
|
412
|
-
private_instance_methods(false) |
|
413
|
-
%i[super define_singleton_method self]
|
414
|
-
).map(&:to_s).freeze
|
415
|
-
# rubocop:enable Layout/ClassStructure
|
415
|
+
define_singleton_method("#{key}?") do
|
416
|
+
!!self.[](key)
|
417
|
+
end
|
416
418
|
end
|
417
419
|
|
418
|
-
#
|
420
|
+
# @param key [Symbol, String]
|
421
|
+
# @return [String]
|
422
|
+
#
|
423
|
+
# @raise [Qonfig::ArgumentError]
|
424
|
+
# @see Qonfig::Settings::KeyGuard
|
425
|
+
#
|
426
|
+
# @api private
|
427
|
+
# @since 0.2.0
|
428
|
+
def __indifferently_accessable_option_key__(key)
|
429
|
+
KeyGuard.new(key).prevent_incompatible_key_type!
|
430
|
+
key.to_s
|
431
|
+
end
|
432
|
+
|
433
|
+
# @param key [Symbol, String]
|
434
|
+
# @return [void]
|
435
|
+
#
|
436
|
+
# @raise [Qonfig::CoreMethodIntersectionError]
|
437
|
+
# @see Qonfig::Settings::KeyGuard
|
438
|
+
#
|
439
|
+
# @api private
|
440
|
+
# @since 0.2.0
|
441
|
+
def __prevent_core_method_intersection__(key)
|
442
|
+
KeyGuard.new(key).prevent_core_method_intersection!
|
443
|
+
end
|
444
|
+
|
445
|
+
# rubocop:disable Layout/ClassStructure
|
446
|
+
# @return [Array<String>]
|
447
|
+
#
|
448
|
+
# @api private
|
449
|
+
# @since 0.2.0
|
450
|
+
CORE_METHODS = Array(
|
451
|
+
instance_methods(false) |
|
452
|
+
private_instance_methods(false) |
|
453
|
+
%i[super define_singleton_method self]
|
454
|
+
).map(&:to_s).freeze
|
455
|
+
# rubocop:enable Layout/ClassStructure
|
419
456
|
end
|
457
|
+
# rubocop:enable Metrics/ClassLength
|