Class: Dry::Configurable::Config
- Inherits:
-
Object
- Object
- Dry::Configurable::Config
- Defined in:
- lib/dry/configurable/config.rb
Overview
Config exposes setting values through a convenient API
Instance Attribute Summary collapse
- #_settings ⇒ Object readonly private
- #_values ⇒ Object readonly private
Instance Method Summary collapse
-
#[](name) ⇒ Object
Get config value by a key.
-
#[]=(name, value) ⇒ Object
Set config value.
- #_dry_equalizer_hash ⇒ Object private
-
#configured?(key) ⇒ Bool
Returns true if the value for the given key has been set on this config.
- #dup_for_settings(settings) ⇒ Object private
- #finalize!(freeze_values: false) ⇒ Object
- #hash ⇒ Object
-
#initialize(settings, values: {}) ⇒ Config
constructor
private
A new instance of Config.
- #pristine ⇒ Object private
-
#to_data ⇒ Data
Returns a frozen Data representation of the config’s resolved values.
-
#to_h ⇒ Hash
Returns config values as a hash, with nested values also converted from Config instances into hashes.
-
#update(values) ⇒ Config
Update config with new values.
-
#values ⇒ Hash
Returns the current config values.
Constructor Details
#initialize(settings, values: {}) ⇒ Config
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Config.
22 23 24 25 26 |
# File 'lib/dry/configurable/config.rb', line 22 def initialize(settings, values: {}) @_settings = settings @_values = values @_configured = Set.new end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object (private)
233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/dry/configurable/config.rb', line 233 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 |
Instance Attribute Details
#_settings ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
12 13 14 |
# File 'lib/dry/configurable/config.rb', line 12 def _settings @_settings end |
#_values ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
15 16 17 |
# File 'lib/dry/configurable/config.rb', line 15 def _values @_values end |
Instance Method Details
#[](name) ⇒ Object
Get config value by a key
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/dry/configurable/config.rb', line 45 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) ⇒ Object
Set config value. Note that finalized configs cannot be changed.
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/dry/configurable/config.rb', line 67 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 ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
147 |
# File 'lib/dry/configurable/config.rb', line 147 alias_method :_dry_equalizer_hash, :hash |
#configured?(key) ⇒ Bool
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.
114 115 116 117 118 119 120 |
# File 'lib/dry/configurable/config.rb', line 114 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) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
36 37 38 |
# File 'lib/dry/configurable/config.rb', line 36 def dup_for_settings(settings) dup.tap { |config| config.instance_variable_set(:@_settings, settings) } end |
#finalize!(freeze_values: false) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/dry/configurable/config.rb', line 199 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 ⇒ Object
150 151 152 153 154 |
# File 'lib/dry/configurable/config.rb', line 150 def hash return @__hash__ if instance_variable_defined?(:@__hash__) _dry_equalizer_hash end |
#pristine ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
221 222 223 |
# File 'lib/dry/configurable/config.rb', line 221 def pristine self.class.new(_settings) end |
#to_data ⇒ Data
Returns a frozen Data representation of the config’s resolved values.
The Data exposes each setting as a real method, sidestepping the #method_missing dispatch on the read path. Intended for performance-sensitive code that reads the same config repeatedly (e.g. per-request render hot paths). A new object is returned per call, so consumers should memoize the result.
Only available on a finalized config. Nested configs are converted recursively to nested Data instances. Values are captured by reference, so in-place mutation of a captured value remains visible through the Data; finalize with ‘freeze_values: true` if you want to prevent that.
The returned Data uses Ruby’s default structural ‘==`/`eql?`/`hash`. If you want to use it as an identity-based cache key (e.g. to skip walking N members on every lookup), memoize the reference yourself and either:
1. key it by `object_id` directly:
@cached = view_class.config.to_data
cache[@cached.object_id] = ...
2. use a `compare_by_identity` cache:
cache = {}.compare_by_identity
cache[@cached] = ...
Either avoids the contract-breaking ‘hash = object_id` override and keeps Data’s structural equality available for general use.
190 191 192 193 194 195 196 |
# File 'lib/dry/configurable/config.rb', line 190 def to_data unless frozen? raise FrozenConfigError, "config must be finalized before #to_data can be called" end _settings.data_class.new(**to_data_attrs) end |
#to_h ⇒ Hash
Returns config values as a hash, with nested values also converted from Dry::Configurable::Config instances into hashes.
142 143 144 |
# File 'lib/dry/configurable/config.rb', line 142 def to_h values.transform_values { |value| value.is_a?(self.class) ? value.to_h : value } end |
#update(values) ⇒ Config
Update config with new values
88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/dry/configurable/config.rb', line 88 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 ⇒ Hash
Returns the current config values.
Nested configs remain in their Dry::Configurable::Config instances.
129 130 131 132 133 134 |
# File 'lib/dry/configurable/config.rb', line 129 def values # Ensure all settings are represented in values _settings.each { |setting| self[setting.name] unless _values.key?(setting.name) } _values end |