class Dry::Configurable::Config

Config exposes setting values through a convenient API

@api public

Attributes

_configured[R]

@api private

_settings[R]

@api private

_values[R]

@api private

Public Class Methods

new(settings, values: {}) click to toggle source

@api private

# File lib/dry/configurable/config.rb, line 24
def initialize(settings, values: {})
  @_settings = settings
  @_values = values
  @_configured = Set.new
end

Public Instance Methods

[](name) click to toggle source

Get config value by a key

@param [String,Symbol] name

@return Config value

# File lib/dry/configurable/config.rb, line 47
def [](name)
  name = name.to_sym

  unless (setting = _settings[name])
    raise ArgumentError, "+#{name}+ is not a setting name"
  end

  _values.fetch(name) {
    # Mutable settings may be configured after read
    _configured.add(name) if setting.cloneable?

    setting.to_value.tap { |value|
      _values[name] = value
    }
  }
end
[]=(name, value) click to toggle source

Set config value. Note that finalized configs cannot be changed.

@param [String,Symbol] name @param [Object] value

# File lib/dry/configurable/config.rb, line 69
def []=(name, value)
  raise FrozenConfigError, "Cannot modify frozen config" if frozen?

  name = name.to_sym

  unless (setting = _settings[name])
    raise ArgumentError, "+#{name}+ is not a setting name"
  end

  _configured.add(name)

  _values[name] = setting.constructor.(value)
end
_dry_equalizer_hash()

@api private

Alias for: hash
configured?(key) click to toggle source

Returns true if the value for the given key has been set on this config.

For simple values, this returns true if the value has been explicitly assigned.

For cloneable (mutable) values, since these are captured on read, returns true if the value does not compare equally to its corresdponing default value. This relies on these objects having functioning ‘#==` checks.

@return [Bool]

@api public

# File lib/dry/configurable/config.rb, line 116
def configured?(key)
  if _configured.include?(key) && _settings[key].cloneable?
    return _values[key] != _settings[key].to_value
  end

  _configured.include?(key)
end
dup_for_settings(settings) click to toggle source

@api private

# File lib/dry/configurable/config.rb, line 38
def dup_for_settings(settings)
  dup.tap { |config| config.instance_variable_set(:@_settings, settings) }
end
finalize!(freeze_values: false) click to toggle source

@api public

# File lib/dry/configurable/config.rb, line 159
def finalize!(freeze_values: false)
  return self if frozen?

  values.each_value do |value|
    if value.is_a?(self.class)
      value.finalize!(freeze_values: freeze_values)
    elsif freeze_values
      value.freeze
    end
  end

  # Memoize the hash for the object when finalizing (regardless of whether values themselves
  # are to be frozen; the intention of finalization is that no further changes should be
  # made). The benefit of freezing the hash at this point is that it saves repeated expensive
  # computation (through Dry::Equalizer's hash implementation) if that hash is to be used
  # later in performance-sensitive situations, such as when serving as a cache key or similar.
  @__hash__ = _dry_equalizer_hash

  freeze
end
hash() click to toggle source

@api public

# File lib/dry/configurable/config.rb, line 152
def hash
  return @__hash__ if instance_variable_defined?(:@__hash__)

  _dry_equalizer_hash
end
Also aliased as: _dry_equalizer_hash
pristine() click to toggle source

@api private

# File lib/dry/configurable/config.rb, line 181
def pristine
  self.class.new(_settings)
end
to_h() click to toggle source

Returns config values as a hash, with nested values also converted from {Config} instances into hashes.

@return [Hash]

@api public

# File lib/dry/configurable/config.rb, line 144
def to_h
  values.to_h { |key, value| [key, value.is_a?(self.class) ? value.to_h : value] }
end
update(values) click to toggle source

Update config with new values

@param values [Hash, to_hash] A hash with new values

@return [Config]

@api public

# File lib/dry/configurable/config.rb, line 90
def update(values)
  values.each do |key, value|
    if self[key].is_a?(self.class)
      unless value.respond_to?(:to_hash)
        raise ArgumentError, "#{value.inspect} is not a valid setting value"
      end

      self[key].update(value.to_hash)
    else
      self[key] = value
    end
  end
  self
end
values() click to toggle source

Returns the current config values.

Nested configs remain in their {Config} instances.

@return [Hash]

@api public

# File lib/dry/configurable/config.rb, line 131
def values
  # Ensure all settings are represented in values
  _settings.each { |setting| self[setting.name] unless _values.key?(setting.name) }

  _values
end

Private Instance Methods

dup_values() click to toggle source
# File lib/dry/configurable/config.rb, line 208
def dup_values
  _values.each_with_object({}) { |(key, val), dup_hsh|
    dup_hsh[key] = _settings[key].cloneable? ? val.dup : val
  }
end
initialize_copy(source) click to toggle source

@api private

Calls superclass method
# File lib/dry/configurable/config.rb, line 31
        def initialize_copy(source)
  super
  @_values = source.__send__(:dup_values)
  @_configured = source._configured.dup
end
method_missing(name, *args) click to toggle source
Calls superclass method
# File lib/dry/configurable/config.rb, line 187
def method_missing(name, *args)
  setting_name = setting_name_from_method(name)
  setting = _settings[setting_name]

  super unless setting

  if name.end_with?("=")
    self[setting_name] = args[0]
  else
    self[setting_name]
  end
end
respond_to_missing?(meth, include_private = false) click to toggle source
Calls superclass method
# File lib/dry/configurable/config.rb, line 200
def respond_to_missing?(meth, include_private = false)
  _settings.key?(setting_name_from_method(meth)) || super
end
setting_name_from_method(method_name) click to toggle source
# File lib/dry/configurable/config.rb, line 204
def setting_name_from_method(method_name)
  method_name.to_s.tr("=", "").to_sym
end