complex_config 0.22.3 → 0.23.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/CHANGES.md +36 -19
- data/README.md +610 -105
- data/Rakefile +6 -4
- data/VERSION +1 -1
- data/bin/complex_config +31 -1
- data/complex_config.gemspec +4 -3
- data/lib/complex_config/config.rb +46 -1
- data/lib/complex_config/encryption.rb +58 -0
- data/lib/complex_config/errors.rb +88 -0
- data/lib/complex_config/key_source.rb +32 -0
- data/lib/complex_config/provider/shortcuts.rb +34 -0
- data/lib/complex_config/provider.rb +342 -0
- data/lib/complex_config/proxy.rb +32 -0
- data/lib/complex_config/railtie.rb +5 -0
- data/lib/complex_config/settings.rb +374 -2
- data/lib/complex_config/tree.rb +93 -0
- data/lib/complex_config/version.rb +1 -1
- data/lib/complex_config.rb +13 -0
- data/spec/spec_helper.rb +4 -5
- metadata +17 -3
@@ -2,15 +2,54 @@ require 'json'
|
|
2
2
|
require 'tins/xt/ask_and_send'
|
3
3
|
require 'tins/thread_local'
|
4
4
|
|
5
|
+
# A settings class that provides structured access to configuration data
|
6
|
+
#
|
7
|
+
# The Settings class serves as a container for configuration values, offering
|
8
|
+
# nested access through method calls and providing utilities for converting
|
9
|
+
# between different representations like hashes, YAML, and JSON. It supports
|
10
|
+
# environment-specific lookups and can be deeply frozen to prevent modification
|
11
|
+
# after initialization.
|
12
|
+
#
|
13
|
+
# @see ComplexConfig::Provider
|
14
|
+
# @see ComplexConfig::Config
|
15
|
+
# @see ComplexConfig::Settings#to_h
|
16
|
+
# @see ComplexConfig::Settings#to_yaml
|
17
|
+
# @see ComplexConfig::Settings#to_json
|
5
18
|
class ComplexConfig::Settings < BasicObject
|
6
19
|
include ::Kernel
|
7
20
|
include ::Tins::AskAndSend
|
8
21
|
|
9
22
|
class << self
|
23
|
+
|
24
|
+
# The [] method converts a hash-like object into a Settings object
|
25
|
+
#
|
26
|
+
# This method serves as a convenience accessor that delegates to the
|
27
|
+
# from_hash class method, enabling quick conversion of hash-like structures
|
28
|
+
# into ComplexConfig::Settings objects for structured configuration access.
|
29
|
+
#
|
30
|
+
# @param a [Object] the object to convert, which may respond to to_hash or to_ary
|
31
|
+
#
|
32
|
+
# @return [ComplexConfig::Settings, Array, Object] a Settings object if the
|
33
|
+
# input responds to to_hash, an array of converted elements if it responds to
|
34
|
+
# to_ary, or the original object if neither applies
|
35
|
+
#
|
36
|
+
# @see ComplexConfig::Settings.from_hash for the underlying conversion logic
|
10
37
|
def [](*a)
|
11
38
|
from_hash(*a)
|
12
39
|
end
|
13
40
|
|
41
|
+
# The from_hash method converts a hash-like object into a Settings object
|
42
|
+
#
|
43
|
+
# This method recursively processes hash-like objects and arrays,
|
44
|
+
# converting them into Settings objects with appropriate nested structures
|
45
|
+
# while preserving non-hash, non-array values as-is
|
46
|
+
#
|
47
|
+
# @param object [Object] the object to convert, which may respond to
|
48
|
+
# to_hash or to_ary
|
49
|
+
#
|
50
|
+
# @return [ComplexConfig::Settings, Array, Object] a Settings object if the
|
51
|
+
# input responds to to_hash, an array of converted elements if it
|
52
|
+
# responds to to_ary, or the original object if neither applies
|
14
53
|
def from_hash(object)
|
15
54
|
case
|
16
55
|
when object.respond_to?(:to_hash)
|
@@ -26,6 +65,24 @@ class ComplexConfig::Settings < BasicObject
|
|
26
65
|
end
|
27
66
|
end
|
28
67
|
|
68
|
+
# The build method constructs a Settings object from a hash with optional
|
69
|
+
# name prefixing
|
70
|
+
#
|
71
|
+
# This method takes a name and hash, sets the name as the prefix for the
|
72
|
+
# Settings object, validates that the hash can be converted to a hash, then
|
73
|
+
# converts it using from_hash. It ensures the name_prefix is reset to nil
|
74
|
+
# after the operation completes.
|
75
|
+
#
|
76
|
+
# @param name [String, nil] The name to use as prefix for the Settings
|
77
|
+
# object, or nil
|
78
|
+
#
|
79
|
+
# @param hash [Object] The object to convert to a Settings object, must
|
80
|
+
# respond to to_hash
|
81
|
+
#
|
82
|
+
# @return [ComplexConfig::Settings] A new Settings object built from the
|
83
|
+
# provided hash
|
84
|
+
#
|
85
|
+
# @raise [TypeError] if the hash parameter does not respond to to_hash
|
29
86
|
def build(name, hash)
|
30
87
|
name.nil? or self.name_prefix = name.to_sym
|
31
88
|
hash.respond_to?(:to_hash) or raise TypeError, 'require hash to build'
|
@@ -36,11 +93,37 @@ class ComplexConfig::Settings < BasicObject
|
|
36
93
|
|
37
94
|
extend Tins::ThreadLocal
|
38
95
|
|
96
|
+
# The thread_local method sets up a thread-local variable for the
|
97
|
+
# name_prefix attribute
|
98
|
+
#
|
99
|
+
# This method configures a thread-local storage mechanism for the
|
100
|
+
# name_prefix attribute, allowing each thread to maintain its own
|
101
|
+
# independent value for this attribute while sharing the same class-level
|
102
|
+
# configuration.
|
103
|
+
#
|
104
|
+
# @return [String] the name prefix of the setting
|
39
105
|
thread_local :name_prefix
|
40
106
|
end
|
41
107
|
|
108
|
+
# The name_prefix attribute accessor provides read and write access to the
|
109
|
+
# name prefix setting
|
110
|
+
#
|
111
|
+
# This method allows getting and setting the name_prefix instance variable,
|
112
|
+
# which is used to prefix configuration keys and provide context for
|
113
|
+
# configuration lookups.
|
114
|
+
#
|
115
|
+
# @attr [String, nil] name_prefix the new name prefix value that was set
|
42
116
|
attr_accessor :name_prefix
|
43
117
|
|
118
|
+
# The initialize method sets up a new Settings object with optional hash
|
119
|
+
# initialization
|
120
|
+
#
|
121
|
+
# This method creates a new instance of the Settings class, initializing it
|
122
|
+
# with an optional hash of values. It sets the name_prefix from the
|
123
|
+
# class-level attribute and prepares an internal table for storing
|
124
|
+
# configuration attributes.
|
125
|
+
#
|
126
|
+
# @param hash [Hash, nil] An optional hash containing initial configuration values
|
44
127
|
def initialize(hash = nil)
|
45
128
|
self.name_prefix = self.class.name_prefix
|
46
129
|
@table = {}
|
@@ -52,24 +135,75 @@ class ComplexConfig::Settings < BasicObject
|
|
52
135
|
end
|
53
136
|
end
|
54
137
|
|
138
|
+
# The initialize_copy method creates a duplicate of the current object
|
139
|
+
#
|
140
|
+
# This method is called when an object is being duplicated, typically through
|
141
|
+
# the dup or clone methods. It performs a deep copy of the internal table
|
142
|
+
# structure while preserving the object's state and ensuring that
|
143
|
+
# modifications to the copy don't affect the original object.
|
144
|
+
#
|
145
|
+
# @param orig [Object] The original object being copied
|
146
|
+
# @return [self] Returns the duplicated object instance for chaining
|
55
147
|
def initialize_copy(orig)
|
56
148
|
super
|
57
149
|
@table = @table.dup
|
58
150
|
self
|
59
151
|
end
|
60
152
|
|
153
|
+
# The attribute_set? method checks whether a specific attribute has been set
|
154
|
+
# in the configuration
|
155
|
+
#
|
156
|
+
# This method verifies if a given attribute name exists in the internal table
|
157
|
+
# of configuration settings, returning true if it has been explicitly set and
|
158
|
+
# false otherwise. It converts the provided name to a symbol before
|
159
|
+
# performing the lookup.
|
160
|
+
#
|
161
|
+
# @param name [Object] the name of the attribute to check for existence
|
162
|
+
# @return [TrueClass, FalseClass] true if the attribute is set, false otherwise
|
61
163
|
def attribute_set?(name)
|
62
164
|
@table.key?(name.to_sym)
|
63
165
|
end
|
64
166
|
|
167
|
+
# The attribute_names method retrieves all attribute names stored in the
|
168
|
+
# configuration
|
169
|
+
#
|
170
|
+
# This method provides access to the internal table of attribute names that
|
171
|
+
# have been set on the current Settings object. It returns an array
|
172
|
+
# containing all the symbolized keys that represent the configured
|
173
|
+
# attributes.
|
174
|
+
#
|
175
|
+
# @return [Array<Symbol>] an array of symbolized attribute names that have
|
176
|
+
# been set on this Settings object
|
65
177
|
def attribute_names
|
66
178
|
@table.keys
|
67
179
|
end
|
68
180
|
|
181
|
+
# The attribute_values method retrieves all values stored in the
|
182
|
+
# configuration table
|
183
|
+
#
|
184
|
+
# This method provides access to the internal table of configuration values,
|
185
|
+
# returning an array containing all the values that have been set on the
|
186
|
+
# current Settings object. It exposes the underlying data structure for
|
187
|
+
# direct inspection or processing.
|
188
|
+
#
|
189
|
+
# @return [Array<Object>] an array of all configuration values stored in the
|
190
|
+
# table
|
69
191
|
def attribute_values
|
70
192
|
@table.values
|
71
193
|
end
|
72
194
|
|
195
|
+
# The attributes_update method merges configuration attributes from another
|
196
|
+
# source
|
197
|
+
#
|
198
|
+
# This method updates the current object's internal table with attributes
|
199
|
+
# from another source, converting it to a Settings object if necessary. It
|
200
|
+
# performs a deep merge of the attribute data while preserving the existing
|
201
|
+
# structure.
|
202
|
+
#
|
203
|
+
# @param other [Object] the source containing attributes to merge, which can
|
204
|
+
# be any object that responds to to_hash or to_ary
|
205
|
+
#
|
206
|
+
# @return [void] Returns nothing
|
73
207
|
def attributes_update(other)
|
74
208
|
unless other.is_a? self.class
|
75
209
|
other = self.class.from_hash(other)
|
@@ -77,6 +211,18 @@ class ComplexConfig::Settings < BasicObject
|
|
77
211
|
@table.update(other.table)
|
78
212
|
end
|
79
213
|
|
214
|
+
# The attributes_update_if_nil method merges configuration attributes from
|
215
|
+
# another source, updating only nil values
|
216
|
+
#
|
217
|
+
# This method updates the current object's internal table with attributes
|
218
|
+
# from another source, but only assigns new values when the existing keys
|
219
|
+
# have nil values. It preserves existing non-nil attribute values while
|
220
|
+
# allowing nil values to be overridden.
|
221
|
+
#
|
222
|
+
# @param other [Object] the source containing attributes to merge, which can
|
223
|
+
# be any object that responds to to_hash or to_ary
|
224
|
+
#
|
225
|
+
# @return [void] Returns nothing
|
80
226
|
def attributes_update_if_nil(other)
|
81
227
|
unless other.is_a? self.class
|
82
228
|
other = self.class.from_hash(other)
|
@@ -86,6 +232,18 @@ class ComplexConfig::Settings < BasicObject
|
|
86
232
|
end
|
87
233
|
end
|
88
234
|
|
235
|
+
# The replace_attributes method replaces all attributes with those from the
|
236
|
+
# provided hash
|
237
|
+
#
|
238
|
+
# This method updates the current object's internal table by replacing all
|
239
|
+
# existing attributes with new ones derived from the given hash. It converts
|
240
|
+
# the hash into a Settings object structure and then updates the internal
|
241
|
+
# table with the new data.
|
242
|
+
#
|
243
|
+
# @param hash [Object] the source containing attributes to replace with,
|
244
|
+
# which can be any object that responds to to_hash or to_ary
|
245
|
+
#
|
246
|
+
# @return [self] returns self to allow for method chaining
|
89
247
|
def replace_attributes(hash)
|
90
248
|
@table = self.class.from_hash(hash).table
|
91
249
|
self
|
@@ -98,10 +256,19 @@ class ComplexConfig::Settings < BasicObject
|
|
98
256
|
# self
|
99
257
|
#end
|
100
258
|
|
259
|
+
# The to_h method converts the settings object into a hash representation
|
260
|
+
#
|
261
|
+
# This method recursively transforms the internal table of configuration
|
262
|
+
# attributes into a nested hash structure, preserving the hierarchical
|
263
|
+
# organization of settings while handling various value types including
|
264
|
+
# arrays, nested settings objects, and primitive values.
|
265
|
+
#
|
266
|
+
# @return [Hash] a hash representation of the settings object with all nested
|
267
|
+
# structures converted to their hash equivalents
|
101
268
|
def to_h
|
102
269
|
table_enumerator.each_with_object({}) do |(k, v), h|
|
103
270
|
h[k] =
|
104
|
-
if
|
271
|
+
if v.respond_to?(:to_ary)
|
105
272
|
v.to_ary.map { |x| (x.ask_and_send(:to_h) rescue x) || x }
|
106
273
|
elsif v.respond_to?(:to_h)
|
107
274
|
if v.nil?
|
@@ -115,30 +282,97 @@ class ComplexConfig::Settings < BasicObject
|
|
115
282
|
end
|
116
283
|
end
|
117
284
|
|
285
|
+
# The == method compares this settings object with another object for
|
286
|
+
# equality
|
287
|
+
#
|
288
|
+
# This method checks if the given object responds to to_h and then compares
|
289
|
+
# the hash representation of this settings object with the hash
|
290
|
+
# representation of the other object to determine if they are equal
|
291
|
+
#
|
292
|
+
# @param other [Object] the object to compare with this settings object
|
293
|
+
# @return [TrueClass, FalseClass] true if the other object responds to to_h
|
294
|
+
# and their hash representations are equal, false otherwise
|
118
295
|
def ==(other)
|
119
296
|
other.respond_to?(:to_h) && to_h == other.to_h
|
120
297
|
end
|
121
298
|
|
299
|
+
# The to_yaml method converts the settings object into YAML format
|
300
|
+
#
|
301
|
+
# This method transforms the configuration data stored in the settings object
|
302
|
+
# into a YAML string representation, making it suitable for serialization and
|
303
|
+
# storage in YAML files.
|
304
|
+
#
|
305
|
+
# @return [String] a YAML formatted string representation of the settings object
|
122
306
|
def to_yaml
|
123
307
|
to_h.to_yaml
|
124
308
|
end
|
125
309
|
|
310
|
+
# The to_json method converts the settings object into JSON format
|
311
|
+
#
|
312
|
+
# This method transforms the configuration data stored in the settings object
|
313
|
+
# into a JSON string representation, making it suitable for serialization and
|
314
|
+
# interchange with other systems that consume JSON data.
|
315
|
+
#
|
316
|
+
# @param a [Array] Additional arguments to pass to the underlying to_json method
|
317
|
+
#
|
318
|
+
# @return [String] a JSON formatted string representation of the settings object
|
126
319
|
def to_json(*a)
|
127
320
|
to_h.to_json(*a)
|
128
321
|
end
|
129
322
|
|
323
|
+
# The to_tree method converts the settings object into a tree representation
|
324
|
+
#
|
325
|
+
# This method transforms the hierarchical configuration data stored in the
|
326
|
+
# settings object into a tree structure that can be used for visualization or
|
327
|
+
# display purposes. It utilizes the Tree.convert class method to perform the
|
328
|
+
# actual conversion process.
|
329
|
+
#
|
330
|
+
# @return [ComplexConfig::Tree] a tree representation of the settings object
|
331
|
+
# hierarchy
|
130
332
|
def to_tree
|
131
333
|
::ComplexConfig::Tree.convert(name_prefix, self)
|
132
334
|
end
|
133
335
|
|
336
|
+
# The size method returns the number of attributes in the settings object
|
337
|
+
#
|
338
|
+
# This method counts all configured attributes by enumerating through the
|
339
|
+
# internal table and returning the total number of key-value pairs stored in
|
340
|
+
# the settings object
|
341
|
+
#
|
342
|
+
# @return [Integer] the count of attributes stored in this settings object
|
134
343
|
def size
|
135
344
|
each.count
|
136
345
|
end
|
137
346
|
|
347
|
+
# The empty? method checks whether the settings object contains no attributes
|
348
|
+
#
|
349
|
+
# This method determines if the current Settings object has zero configured
|
350
|
+
# attributes by comparing its size to zero. It provides a convenient way to
|
351
|
+
# test for emptiness without having to manually check the size or iterate
|
352
|
+
# through all attributes.
|
353
|
+
#
|
354
|
+
# @return [TrueClass, FalseClass] true if the settings object has no
|
355
|
+
# attributes, false otherwise
|
138
356
|
def empty?
|
139
357
|
size == 0
|
140
358
|
end
|
141
359
|
|
360
|
+
# The attributes_list method generates a formatted string representation of
|
361
|
+
# all configuration attributes
|
362
|
+
#
|
363
|
+
# This method creates a human-readable list of all configuration attributes
|
364
|
+
# by combining their paths and values into a structured format with
|
365
|
+
# customizable separators for paths and key-value pairs
|
366
|
+
#
|
367
|
+
# @param pair_sep [String] the separator to use between attribute paths and
|
368
|
+
# their values, defaults to ' = '
|
369
|
+
#
|
370
|
+
# @param path_sep [String] the separator to use between path components,
|
371
|
+
# defaults to '.'
|
372
|
+
#
|
373
|
+
# @return [String] a formatted string containing all attribute paths and
|
374
|
+
# their corresponding values or the class name if no attributes are
|
375
|
+
# present
|
142
376
|
def attributes_list(pair_sep: ' = ', path_sep: ?.)
|
143
377
|
empty? and return self.class.name
|
144
378
|
pathes(path_sep: path_sep).inject('') do |result, (path, value)|
|
@@ -146,11 +380,33 @@ class ComplexConfig::Settings < BasicObject
|
|
146
380
|
end
|
147
381
|
end
|
148
382
|
|
149
|
-
|
383
|
+
# The to_s method provides a string representation of the settings object
|
384
|
+
#
|
385
|
+
# This method returns a human-readable string representation of the settings
|
386
|
+
# object, either by returning the class name when the object is empty, or by
|
387
|
+
# converting the object to a tree structure and then to a string for
|
388
|
+
# non-empty objects
|
389
|
+
#
|
390
|
+
# @param a [Array] Additional arguments passed to the method (not used)
|
391
|
+
# @return [String] The string representation of the settings object
|
392
|
+
def to_s(*a)
|
150
393
|
empty? and return self.class.name
|
151
394
|
to_tree.to_s
|
152
395
|
end
|
153
396
|
|
397
|
+
# The pathes method recursively builds a hash of configuration paths and
|
398
|
+
# their values
|
399
|
+
#
|
400
|
+
# This method traverses a nested hash structure and constructs a flattened
|
401
|
+
# hash where keys are dot-separated paths representing the hierarchical
|
402
|
+
# structure of the original data, and values are the corresponding leaf
|
403
|
+
# values from the original structure
|
404
|
+
#
|
405
|
+
# @param hash [Hash] the hash to process, defaults to the instance's table
|
406
|
+
# @param path_sep [String] the separator to use between path components, defaults to '.'
|
407
|
+
# @param prefix [String] the prefix to prepend to each path, defaults to the name_prefix
|
408
|
+
# @param result [Hash] the hash to accumulate results in, defaults to an empty hash
|
409
|
+
# @return [Hash] a flattened hash with paths as keys and values as leaf values
|
154
410
|
def pathes(hash = table, path_sep: ?., prefix: name_prefix.to_s, result: {})
|
155
411
|
hash.each do |key, value|
|
156
412
|
path = prefix.empty? ? key.to_s : "#{prefix}#{path_sep}#{key}"
|
@@ -185,15 +441,40 @@ class ComplexConfig::Settings < BasicObject
|
|
185
441
|
|
186
442
|
alias inspect to_s
|
187
443
|
|
444
|
+
# The pretty_print method formats the object for pretty printing
|
445
|
+
#
|
446
|
+
# This method takes a PrettyPrint object and uses it to format the object's
|
447
|
+
# string representation for display purposes
|
448
|
+
#
|
449
|
+
# @param q [PrettyPrint] the pretty printer object to use for formatting
|
450
|
+
# @return [void] Returns nothing
|
188
451
|
def pretty_print(q)
|
189
452
|
q.text inspect
|
190
453
|
end
|
191
454
|
|
455
|
+
# The freeze method freezes the internal table and calls the superclass
|
456
|
+
# freeze method
|
457
|
+
#
|
458
|
+
# This method ensures that the configuration data stored in the internal
|
459
|
+
# table is frozen, preventing further modifications to the configuration
|
460
|
+
# settings. It then delegates to the parent class's freeze method to complete
|
461
|
+
# the freezing process.
|
462
|
+
#
|
463
|
+
# @return [self] Returns self to allow for method chaining after freezing
|
192
464
|
def freeze
|
193
465
|
@table.freeze
|
194
466
|
super
|
195
467
|
end
|
196
468
|
|
469
|
+
# The deep_freeze method recursively freezes all nested objects within the
|
470
|
+
# configuration
|
471
|
+
#
|
472
|
+
# This method traverses the internal table of configuration attributes and
|
473
|
+
# applies deep freezing to each value, ensuring that all nested settings
|
474
|
+
# objects and their contents are immutable It also freezes the internal table
|
475
|
+
# itself to prevent modification of the attribute structure
|
476
|
+
#
|
477
|
+
# @return [self] Returns self to allow for method chaining after freezing
|
197
478
|
def deep_freeze
|
198
479
|
table_enumerator.each do |_, v|
|
199
480
|
v.ask_and_send(:deep_freeze) || (v.freeze rescue v)
|
@@ -201,6 +482,16 @@ class ComplexConfig::Settings < BasicObject
|
|
201
482
|
freeze
|
202
483
|
end
|
203
484
|
|
485
|
+
# The attribute_get method retrieves a configuration attribute value by name
|
486
|
+
#
|
487
|
+
# This method attempts to fetch a configuration attribute value first from
|
488
|
+
# the internal table, and if the attribute is not set, it applies registered
|
489
|
+
# plugins to generate a value. It provides a unified way to access
|
490
|
+
# configuration attributes that may be dynamically generated.
|
491
|
+
#
|
492
|
+
# @param name [Object] the name of the attribute to retrieve
|
493
|
+
# @return [Object, nil] the value of the attribute if found, or nil if not
|
494
|
+
# found
|
204
495
|
def attribute_get(name)
|
205
496
|
if !attribute_set?(name) and
|
206
497
|
value = ::ComplexConfig::Provider.apply_plugins(self, name)
|
@@ -211,8 +502,18 @@ class ComplexConfig::Settings < BasicObject
|
|
211
502
|
end
|
212
503
|
end
|
213
504
|
|
505
|
+
# Alias for {attribute_get}
|
506
|
+
#
|
507
|
+
# @see attribute_get
|
214
508
|
alias [] attribute_get
|
215
509
|
|
510
|
+
# The attribute_get! method retrieves a configuration attribute value by
|
511
|
+
# name, raising an exception if the attribute is not set
|
512
|
+
#
|
513
|
+
# @param name [Object] the name of the attribute to retrieve
|
514
|
+
# @return [Object] the value of the attribute if found
|
515
|
+
# @raise [ComplexConfig::AttributeMissing] if the attribute is not set and no
|
516
|
+
# plugin can provide a value
|
216
517
|
def attribute_get!(name)
|
217
518
|
if attribute_set?(name)
|
218
519
|
attribute_get(name)
|
@@ -221,32 +522,103 @@ class ComplexConfig::Settings < BasicObject
|
|
221
522
|
end
|
222
523
|
end
|
223
524
|
|
525
|
+
# The []= method assigns a value to a configuration attribute
|
526
|
+
#
|
527
|
+
# This method stores a configuration attribute value in the internal table
|
528
|
+
# using the attribute name as a symbol key. It converts the attribute name
|
529
|
+
# to a symbol before storing the value.
|
530
|
+
#
|
531
|
+
# @param name [Object] the name of the attribute to assign
|
532
|
+
# @param value [Object] the value to assign to the attribute
|
533
|
+
# @return [Object] the assigned value
|
224
534
|
def []=(name, value)
|
225
535
|
@table[name.to_sym] = value
|
226
536
|
end
|
227
537
|
|
538
|
+
# The each method iterates over all configuration attributes
|
539
|
+
#
|
540
|
+
# This method provides enumeration support for the configuration settings,
|
541
|
+
# yielding each key-value pair from the internal table to the provided block.
|
542
|
+
# It delegates to the table enumerator to ensure consistent iteration behavior
|
543
|
+
# across different contexts.
|
544
|
+
#
|
545
|
+
# @yield [key, value] Yields each configuration attribute key and its
|
546
|
+
# corresponding value
|
547
|
+
# @yieldparam key [Object] The configuration attribute key
|
548
|
+
# @yieldparam value [Object] The configuration attribute value
|
549
|
+
# @return [self] Returns self to allow for method chaining after enumeration
|
228
550
|
def each(&block)
|
229
551
|
table_enumerator.each(&block)
|
230
552
|
end
|
231
553
|
|
232
554
|
protected
|
233
555
|
|
556
|
+
# The table attribute reader provides access to the internal hash table
|
557
|
+
# storing configuration attributes
|
558
|
+
#
|
559
|
+
# This method returns the internal @table instance variable that holds all
|
560
|
+
# configuration attributes and their values for this settings object. The
|
561
|
+
# returned hash is used internally for fast lookup of configuration values
|
562
|
+
# and is not intended to be modified directly by external code.
|
563
|
+
#
|
564
|
+
# @return [Hash] the internal hash table containing all configuration
|
565
|
+
# attributes and their values
|
566
|
+
# @api private
|
234
567
|
attr_reader :table
|
235
568
|
|
236
569
|
private
|
237
570
|
|
571
|
+
# The table_enumerator method provides an enumerator for iterating over the
|
572
|
+
# internal configuration table
|
573
|
+
#
|
574
|
+
# This method returns an enumerator object that can be used to iterate over
|
575
|
+
# all key-value pairs stored in the internal @table instance variable. It
|
576
|
+
# delegates to the enum_for method of the @table hash to provide consistent
|
577
|
+
# enumeration behavior.
|
578
|
+
#
|
579
|
+
# @return [Enumerator] an enumerator for the internal configuration table hash
|
238
580
|
def table_enumerator
|
239
581
|
@table.enum_for(:each)
|
240
582
|
end
|
241
583
|
|
584
|
+
# The respond_to_missing? method determines if the object responds to a given
|
585
|
+
# method name
|
586
|
+
#
|
587
|
+
# This method is part of Ruby's method missing protocol and is used to
|
588
|
+
# dynamically determine whether the object should be considered as responding
|
589
|
+
# to a particular method. It checks if the method name ends with a question
|
590
|
+
# mark (indicating a safe navigation query) or if the corresponding attribute
|
591
|
+
# has been explicitly set.
|
592
|
+
#
|
593
|
+
# @param id [Object] the method name being checked
|
594
|
+
# @param include_private [Boolean] whether to consider private methods
|
595
|
+
# (unused in this implementation)
|
596
|
+
# @return [Boolean] true if the object responds to the method, false otherwise
|
242
597
|
def respond_to_missing?(id, include_private = false)
|
243
598
|
id =~ /\?\z/ || attribute_set?(id)
|
244
599
|
end
|
245
600
|
|
601
|
+
# The skip method raises a skip exception to bypass plugin execution
|
602
|
+
#
|
603
|
+
# @return [void] This method always raises a :skip exception and never
|
604
|
+
# returns normally
|
246
605
|
def skip
|
247
606
|
throw :skip
|
248
607
|
end
|
249
608
|
|
609
|
+
# The method_missing method handles dynamic attribute access and assignment
|
610
|
+
#
|
611
|
+
# This method intercepts calls to undefined methods on the Settings object,
|
612
|
+
# providing support for attribute retrieval, assignment, existence checking,
|
613
|
+
# and plugin-based value resolution. It processes method names ending with
|
614
|
+
# '?' for existence checks or safe navigation, '=' for assignment, and other
|
615
|
+
# names for attribute lookup or plugin execution.
|
616
|
+
#
|
617
|
+
# @param id [Object] The name of the method being called
|
618
|
+
# @param a [Array] Arguments passed to the method
|
619
|
+
# @param b [Proc] Block passed to the method
|
620
|
+
#
|
621
|
+
# @return [Object] The result of the dynamic attribute operation
|
250
622
|
def method_missing(id, *a, &b)
|
251
623
|
case
|
252
624
|
when id =~ /\?\z/
|