Class: ComplexConfig::Settings

Inherits:
BasicObject
Extended by:
Tins::ThreadLocal
Includes:
Kernel, Tins::AskAndSend
Defined in:
lib/complex_config/settings.rb

Overview

A settings class that provides structured access to configuration data

The Settings class serves as a container for configuration values, offering nested access through method calls and providing utilities for converting between different representations like hashes, YAML, and JSON. It supports environment-specific lookups and can be deeply frozen to prevent modification after initialization.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash = nil) ⇒ Settings

The initialize method sets up a new Settings object with optional hash initialization

This method creates a new instance of the Settings class, initializing it with an optional hash of values. It sets the name_prefix from the class-level attribute and prepares an internal table for storing configuration attributes.

Parameters:

  • hash (Hash, nil) (defaults to: nil)

    An optional hash containing initial configuration values



127
128
129
130
131
132
133
134
135
136
# File 'lib/complex_config/settings.rb', line 127

def initialize(hash = nil)
  self.name_prefix = self.class.name_prefix
  @table = {}
  if hash
    hash.each_pair do |k, v|
      k = k.to_sym
      @table[k] = v
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(id, *a, &b) ⇒ Object (private)

The method_missing method handles dynamic attribute access and assignment

This method intercepts calls to undefined methods on the Settings object, providing support for attribute retrieval, assignment, existence checking, and plugin-based value resolution. It processes method names ending with ‘?’ for existence checks or safe navigation, ‘=’ for assignment, and other names for attribute lookup or plugin execution.

Parameters:

  • id (Object)

    The name of the method being called

  • a (Array)

    Arguments passed to the method

  • b (Proc)

    Block passed to the method

Returns:

  • (Object)

    The result of the dynamic attribute operation



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
# File 'lib/complex_config/settings.rb', line 622

def method_missing(id, *a, &b)
  case
  when id =~ /\?\z/
    begin
      public_send $`.to_sym, *a, &b
    rescue ::ComplexConfig::AttributeMissing
      nil
    end
  when id =~ /=\z/
    @table[$`.to_sym] = a.first
  when value = ::ComplexConfig::Provider.apply_plugins(self, id)
    value
  else
    if attribute_set?(id)
      @table[id]
    else
      raise ::ComplexConfig::AttributeMissing, "no attribute named #{id.inspect}"
    end
  end
end

Instance Attribute Details

#name_prefixObject

The name_prefix attribute accessor provides read and write access to the name prefix setting

This method allows getting and setting the name_prefix instance variable, which is used to prefix configuration keys and provide context for configuration lookups.



116
117
118
# File 'lib/complex_config/settings.rb', line 116

def name_prefix
  @name_prefix
end

Class Method Details

.[](*a) ⇒ ComplexConfig::Settings, ...

The [] method converts a hash-like object into a Settings object

This method serves as a convenience accessor that delegates to the from_hash class method, enabling quick conversion of hash-like structures into ComplexConfig::Settings objects for structured configuration access.

Parameters:

  • a (Object)

    the object to convert, which may respond to to_hash or to_ary

Returns:

  • (ComplexConfig::Settings, Array, Object)

    a Settings object if the input responds to to_hash, an array of converted elements if it responds to to_ary, or the original object if neither applies

See Also:



37
38
39
# File 'lib/complex_config/settings.rb', line 37

def [](*a)
  from_hash(*a)
end

.build(name, hash) ⇒ ComplexConfig::Settings

The build method constructs a Settings object from a hash with optional name prefixing

This method takes a name and hash, sets the name as the prefix for the Settings object, validates that the hash can be converted to a hash, then converts it using from_hash. It ensures the name_prefix is reset to nil after the operation completes.

Parameters:

  • name (String, nil)

    The name to use as prefix for the Settings object, or nil

  • hash (Object)

    The object to convert to a Settings object, must respond to to_hash

Returns:

Raises:

  • (TypeError)

    if the hash parameter does not respond to to_hash



86
87
88
89
90
91
92
# File 'lib/complex_config/settings.rb', line 86

def build(name, hash)
  name.nil? or self.name_prefix = name.to_sym
  hash.respond_to?(:to_hash) or raise TypeError, 'require hash to build'
  from_hash(hash)
ensure
  self.name_prefix = nil
end

.from_hash(object) ⇒ ComplexConfig::Settings, ...

The from_hash method converts a hash-like object into a Settings object

This method recursively processes hash-like objects and arrays, converting them into Settings objects with appropriate nested structures while preserving non-hash, non-array values as-is

Parameters:

  • object (Object)

    the object to convert, which may respond to to_hash or to_ary

Returns:

  • (ComplexConfig::Settings, Array, Object)

    a Settings object if the input responds to to_hash, an array of converted elements if it responds to to_ary, or the original object if neither applies



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/complex_config/settings.rb', line 53

def from_hash(object)
  case
  when object.respond_to?(:to_hash)
    result = new
    object.to_hash.each do |key, value|
      result[key] = from_hash(value)
    end
    result
  when object.respond_to?(:to_ary)
    object.to_ary.map { |a| from_hash(a) }
  else
    object
  end
end

.name_prefixString

The thread_local method sets up a thread-local variable for the name_prefix attribute

This method configures a thread-local storage mechanism for the name_prefix attribute, allowing each thread to maintain its own independent value for this attribute while sharing the same class-level configuration.

Returns:

  • (String)

    the name prefix of the setting



105
# File 'lib/complex_config/settings.rb', line 105

thread_local :name_prefix

Instance Method Details

#==(other) ⇒ TrueClass, FalseClass

The == method compares this settings object with another object for equality

This method checks if the given object responds to to_h and then compares the hash representation of this settings object with the hash representation of the other object to determine if they are equal

Parameters:

  • other (Object)

    the object to compare with this settings object

Returns:

  • (TrueClass, FalseClass)

    true if the other object responds to to_h and their hash representations are equal, false otherwise



295
296
297
# File 'lib/complex_config/settings.rb', line 295

def ==(other)
  other.respond_to?(:to_h) && to_h == other.to_h
end

#[]=(name, value) ⇒ Object

The []= method assigns a value to a configuration attribute

This method stores a configuration attribute value in the internal table using the attribute name as a symbol key. It converts the attribute name to a symbol before storing the value.

Parameters:

  • name (Object)

    the name of the attribute to assign

  • value (Object)

    the value to assign to the attribute

Returns:

  • (Object)

    the assigned value



534
535
536
# File 'lib/complex_config/settings.rb', line 534

def []=(name, value)
  @table[name.to_sym] = value
end

#attribute_get(name) ⇒ Object? Also known as: []

The attribute_get method retrieves a configuration attribute value by name

This method attempts to fetch a configuration attribute value first from the internal table, and if the attribute is not set, it applies registered plugins to generate a value. It provides a unified way to access configuration attributes that may be dynamically generated.

Parameters:

  • name (Object)

    the name of the attribute to retrieve

Returns:

  • (Object, nil)

    the value of the attribute if found, or nil if not found



495
496
497
498
499
500
501
502
503
# File 'lib/complex_config/settings.rb', line 495

def attribute_get(name)
  if !attribute_set?(name) and
    value = ::ComplexConfig::Provider.apply_plugins(self, name)
  then
    value
  else
    @table[name.to_sym]
  end
end

#attribute_get!(name) ⇒ Object

The attribute_get! method retrieves a configuration attribute value by name, raising an exception if the attribute is not set

Parameters:

  • name (Object)

    the name of the attribute to retrieve

Returns:

  • (Object)

    the value of the attribute if found

Raises:



517
518
519
520
521
522
523
# File 'lib/complex_config/settings.rb', line 517

def attribute_get!(name)
  if attribute_set?(name)
    attribute_get(name)
  else
    raise ::ComplexConfig::AttributeMissing, "no attribute named #{name.inspect}"
  end
end

#attribute_namesArray<Symbol>

The attribute_names method retrieves all attribute names stored in the configuration

This method provides access to the internal table of attribute names that have been set on the current Settings object. It returns an array containing all the symbolized keys that represent the configured attributes.

Returns:

  • (Array<Symbol>)

    an array of symbolized attribute names that have been set on this Settings object



177
178
179
# File 'lib/complex_config/settings.rb', line 177

def attribute_names
  @table.keys
end

#attribute_set?(name) ⇒ TrueClass, FalseClass

The attribute_set? method checks whether a specific attribute has been set in the configuration

This method verifies if a given attribute name exists in the internal table of configuration settings, returning true if it has been explicitly set and false otherwise. It converts the provided name to a symbol before performing the lookup.

Parameters:

  • name (Object)

    the name of the attribute to check for existence

Returns:

  • (TrueClass, FalseClass)

    true if the attribute is set, false otherwise



163
164
165
# File 'lib/complex_config/settings.rb', line 163

def attribute_set?(name)
  @table.key?(name.to_sym)
end

#attribute_valuesArray<Object>

The attribute_values method retrieves all values stored in the configuration table

This method provides access to the internal table of configuration values, returning an array containing all the values that have been set on the current Settings object. It exposes the underlying data structure for direct inspection or processing.

table

Returns:

  • (Array<Object>)

    an array of all configuration values stored in the



191
192
193
# File 'lib/complex_config/settings.rb', line 191

def attribute_values
  @table.values
end

#attributes_list(pair_sep: ' = ', path_sep: ?.) ⇒ String

The attributes_list method generates a formatted string representation of all configuration attributes

This method creates a human-readable list of all configuration attributes by combining their paths and values into a structured format with customizable separators for paths and key-value pairs

Parameters:

  • pair_sep (String) (defaults to: ' = ')

    the separator to use between attribute paths and their values, defaults to ‘ = ’

  • path_sep (String) (defaults to: ?.)

    the separator to use between path components, defaults to ‘.’

Returns:

  • (String)

    a formatted string containing all attribute paths and their corresponding values or the class name if no attributes are present



376
377
378
379
380
381
# File 'lib/complex_config/settings.rb', line 376

def attributes_list(pair_sep: ' = ', path_sep: ?.)
  empty? and return self.class.name
  pathes(path_sep: path_sep).inject('') do |result, (path, value)|
    result + "#{path}#{pair_sep}#{value.inspect}\n"
  end
end

#attributes_update(other) ⇒ void

This method returns an undefined value.

The attributes_update method merges configuration attributes from another source

This method updates the current object’s internal table with attributes from another source, converting it to a Settings object if necessary. It performs a deep merge of the attribute data while preserving the existing structure.

Parameters:

  • other (Object)

    the source containing attributes to merge, which can be any object that responds to to_hash or to_ary



207
208
209
210
211
212
# File 'lib/complex_config/settings.rb', line 207

def attributes_update(other)
  unless other.is_a? self.class
    other = self.class.from_hash(other)
  end
  @table.update(other.table)
end

#attributes_update_if_nil(other) ⇒ void

This method returns an undefined value.

The attributes_update_if_nil method merges configuration attributes from another source, updating only nil values

This method updates the current object’s internal table with attributes from another source, but only assigns new values when the existing keys have nil values. It preserves existing non-nil attribute values while allowing nil values to be overridden.

Parameters:

  • other (Object)

    the source containing attributes to merge, which can be any object that responds to to_hash or to_ary



226
227
228
229
230
231
232
233
# File 'lib/complex_config/settings.rb', line 226

def attributes_update_if_nil(other)
  unless other.is_a? self.class
    other = self.class.from_hash(other)
  end
  @table.update(other.table) do |key, oldval, newval|
    @table.key?(key) ? oldval : newval
  end
end

#deep_freezeself

The deep_freeze method recursively freezes all nested objects within the configuration

This method traverses the internal table of configuration attributes and applies deep freezing to each value, ensuring that all nested settings objects and their contents are immutable It also freezes the internal table itself to prevent modification of the attribute structure

Returns:

  • (self)

    Returns self to allow for method chaining after freezing



478
479
480
481
482
483
# File 'lib/complex_config/settings.rb', line 478

def deep_freeze
  table_enumerator.each do |_, v|
    v.ask_and_send(:deep_freeze) || (v.freeze rescue v)
  end
  freeze
end

#each {|key, value| ... } ⇒ self

The each method iterates over all configuration attributes

This method provides enumeration support for the configuration settings, yielding each key-value pair from the internal table to the provided block. It delegates to the table enumerator to ensure consistent iteration behavior across different contexts.

Yields:

  • (key, value)

    Yields each configuration attribute key and its corresponding value

Yield Parameters:

  • key (Object)

    The configuration attribute key

  • value (Object)

    The configuration attribute value

Returns:

  • (self)

    Returns self to allow for method chaining after enumeration



550
551
552
# File 'lib/complex_config/settings.rb', line 550

def each(&block)
  table_enumerator.each(&block)
end

#empty?TrueClass, FalseClass

The empty? method checks whether the settings object contains no attributes

This method determines if the current Settings object has zero configured attributes by comparing its size to zero. It provides a convenient way to test for emptiness without having to manually check the size or iterate through all attributes.

Returns:

  • (TrueClass, FalseClass)

    true if the settings object has no attributes, false otherwise



356
357
358
# File 'lib/complex_config/settings.rb', line 356

def empty?
  size == 0
end

#freezeself

The freeze method freezes the internal table and calls the superclass freeze method

This method ensures that the configuration data stored in the internal table is frozen, preventing further modifications to the configuration settings. It then delegates to the parent class’s freeze method to complete the freezing process.

Returns:

  • (self)

    Returns self to allow for method chaining after freezing



464
465
466
467
# File 'lib/complex_config/settings.rb', line 464

def freeze
  @table.freeze
  super
end

#initialize_copy(orig) ⇒ self

The initialize_copy method creates a duplicate of the current object

This method is called when an object is being duplicated, typically through the dup or clone methods. It performs a deep copy of the internal table structure while preserving the object’s state and ensuring that modifications to the copy don’t affect the original object.

Parameters:

  • orig (Object)

    The original object being copied

Returns:

  • (self)

    Returns the duplicated object instance for chaining



147
148
149
150
151
# File 'lib/complex_config/settings.rb', line 147

def initialize_copy(orig)
  super
  @table = @table.dup
  self
end

#pathes(hash = table, path_sep: ?., prefix: name_prefix.to_s, result: {}) ⇒ Hash

The pathes method recursively builds a hash of configuration paths and their values

This method traverses a nested hash structure and constructs a flattened hash where keys are dot-separated paths representing the hierarchical structure of the original data, and values are the corresponding leaf values from the original structure

Parameters:

  • hash (Hash) (defaults to: table)

    the hash to process, defaults to the instance’s table

  • path_sep (String) (defaults to: ?.)

    the separator to use between path components, defaults to ‘.’

  • prefix (String) (defaults to: name_prefix.to_s)

    the prefix to prepend to each path, defaults to the name_prefix

  • result (Hash) (defaults to: {})

    the hash to accumulate results in, defaults to an empty hash

Returns:

  • (Hash)

    a flattened hash with paths as keys and values as leaf values



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/complex_config/settings.rb', line 410

def pathes(hash = table, path_sep: ?., prefix: name_prefix.to_s, result: {})
  hash.each do |key, value|
    path = prefix.empty? ? key.to_s : "#{prefix}#{path_sep}#{key}"
    case value
    when ::ComplexConfig::Settings
      pathes(
        value,
        path_sep: path_sep,
        prefix:   path,
        result:   result
      )
    when ::Array
      value.each_with_index do |v, i|
        sub_path = path + "[#{i}]"
        if ::ComplexConfig::Settings === v
          pathes(
            v,
            path_sep: path_sep,
            prefix:   sub_path,
            result:   result
          )
        else
          result[sub_path] = v
        end
      end
    else
      result[path] = value
    end
  end
  result
end

#pretty_print(q) ⇒ void

This method returns an undefined value.

The pretty_print method formats the object for pretty printing

This method takes a PrettyPrint object and uses it to format the object’s string representation for display purposes

Parameters:

  • q (PrettyPrint)

    the pretty printer object to use for formatting



451
452
453
# File 'lib/complex_config/settings.rb', line 451

def pretty_print(q)
  q.text inspect
end

#replace_attributes(hash) ⇒ self

The replace_attributes method replaces all attributes with those from the provided hash

This method updates the current object’s internal table by replacing all existing attributes with new ones derived from the given hash. It converts the hash into a Settings object structure and then updates the internal table with the new data.

Parameters:

  • hash (Object)

    the source containing attributes to replace with, which can be any object that responds to to_hash or to_ary

Returns:

  • (self)

    returns self to allow for method chaining



247
248
249
250
# File 'lib/complex_config/settings.rb', line 247

def replace_attributes(hash)
  @table = self.class.from_hash(hash).table
  self
end

#sizeInteger

The size method returns the number of attributes in the settings object

This method counts all configured attributes by enumerating through the internal table and returning the total number of key-value pairs stored in the settings object

Returns:

  • (Integer)

    the count of attributes stored in this settings object



343
344
345
# File 'lib/complex_config/settings.rb', line 343

def size
  each.count
end

#to_hHash

The to_h method converts the settings object into a hash representation

This method recursively transforms the internal table of configuration attributes into a nested hash structure, preserving the hierarchical organization of settings while handling various value types including arrays, nested settings objects, and primitive values.

Returns:

  • (Hash)

    a hash representation of the settings object with all nested structures converted to their hash equivalents



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/complex_config/settings.rb', line 268

def to_h
  table_enumerator.each_with_object({}) do |(k, v), h|
    h[k] =
      if v.respond_to?(:to_ary)
        v.to_ary.map { |x| (x.ask_and_send(:to_h) rescue x) || x }
      elsif v.respond_to?(:to_h)
        if v.nil?
          nil
        else
          v.ask_and_send(:to_h) rescue v
        end
      else
        v
      end
  end
end

#to_json(*a) ⇒ String

The to_json method converts the settings object into JSON format

This method transforms the configuration data stored in the settings object into a JSON string representation, making it suitable for serialization and interchange with other systems that consume JSON data.

Parameters:

  • a (Array)

    Additional arguments to pass to the underlying to_json method

Returns:

  • (String)

    a JSON formatted string representation of the settings object



319
320
321
# File 'lib/complex_config/settings.rb', line 319

def to_json(*a)
  to_h.to_json(*a)
end

#to_s(*a) ⇒ String Also known as: inspect

The to_s method provides a string representation of the settings object

This method returns a human-readable string representation of the settings object, either by returning the class name when the object is empty, or by converting the object to a tree structure and then to a string for non-empty objects

Parameters:

  • a (Array)

    Additional arguments passed to the method (not used)

Returns:

  • (String)

    The string representation of the settings object



392
393
394
395
# File 'lib/complex_config/settings.rb', line 392

def to_s(*a)
  empty? and return self.class.name
  to_tree.to_s
end

#to_treeComplexConfig::Tree

The to_tree method converts the settings object into a tree representation

This method transforms the hierarchical configuration data stored in the settings object into a tree structure that can be used for visualization or display purposes. It utilizes the Tree.convert class method to perform the actual conversion process.

Returns:



332
333
334
# File 'lib/complex_config/settings.rb', line 332

def to_tree
  ::ComplexConfig::Tree.convert(name_prefix, self)
end

#to_yamlString

The to_yaml method converts the settings object into YAML format

This method transforms the configuration data stored in the settings object into a YAML string representation, making it suitable for serialization and storage in YAML files.

Returns:

  • (String)

    a YAML formatted string representation of the settings object



306
307
308
# File 'lib/complex_config/settings.rb', line 306

def to_yaml
  to_h.to_yaml
end