dry-configurable 0.12.1 → 0.16.1
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/CHANGELOG.md +118 -0
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/dry-configurable.gemspec +16 -15
- data/lib/dry/configurable/class_methods.rb +37 -19
- data/lib/dry/configurable/compiler.rb +5 -12
- data/lib/dry/configurable/config.rb +116 -46
- data/lib/dry/configurable/constants.rb +1 -1
- data/lib/dry/configurable/dsl.rb +36 -22
- data/lib/dry/configurable/extension.rb +48 -0
- data/lib/dry/configurable/instance_methods.rb +6 -6
- data/lib/dry/configurable/methods.rb +3 -7
- data/lib/dry/configurable/setting.rb +29 -95
- data/lib/dry/configurable/settings.rb +10 -26
- data/lib/dry/configurable/version.rb +1 -1
- data/lib/dry/configurable.rb +27 -20
- data/lib/dry-configurable.rb +1 -1
- metadata +12 -18
- data/lib/dry/configurable/dsl/args.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d8c3e4ebee8cf7f978c48580f64c1547c6c818b50ed7064b0758b4bffb072ee
|
4
|
+
data.tar.gz: 2aa701383b59289fbe591100642027fc5bc0d074bd0ec5d6d085359293af0f8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 221e2cfb38c4eae38ab6b56250e2d70672c9d1e6883b048f5a6bc807d0996065bf1b8e4a102fd78b6a95a4a4ffcf21dcfd46c64737acd915b3d1b80f9dca273e
|
7
|
+
data.tar.gz: 1f04a6b9af22d12a6b310902cdf5761362762a7fcca97c78a2feb17a28ce3199285a8cd1b6e80c56cde10f7fc2983c8598990fa263e5e55656502ad22761dd2e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,123 @@
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
2
|
|
3
|
+
## 0.16.1 2022-10-13
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
|
7
|
+
- Restored performance of config value reads (direct reader methods as well as aggregate methods like `#values` and `#to_h`) to pre-0.16.0 levels (#149 by @timriley)
|
8
|
+
|
9
|
+
[Compare v0.16.0...v0.16.1](https://github.com/dry-rb/dry-configurable/compare/v0.16.0...v0.16.1)
|
10
|
+
|
11
|
+
## 0.16.0 2022-10-08
|
12
|
+
|
13
|
+
|
14
|
+
### Added
|
15
|
+
|
16
|
+
- Support for custom config classes via `config_class:` option (#136 by @solnic)
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
extend Dry::Configurable(config_class: MyConfig)
|
20
|
+
```
|
21
|
+
|
22
|
+
Your config class should inherit from `Dry::Configurable::Config`.
|
23
|
+
- Return `Dry::Core::Constants::Undefined` (instead of nil) as the value for non-configured settings via a `default_undefined: true` option (#141 by @timriley)
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
extend Dry::Configurable(default_undefined: true)
|
27
|
+
```
|
28
|
+
|
29
|
+
You must opt into this feature via the `default_undefined: true` option. Non-configured setting values are still `nil` by default.
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
|
33
|
+
- Remove exec bit from version.rb (#139 by @Fryguy)
|
34
|
+
|
35
|
+
### Changed
|
36
|
+
|
37
|
+
- Improve memory usage by separating setting definitions from config values (#138 by @timriley)
|
38
|
+
|
39
|
+
Your usage of dry-configurable may be impacted if you have been accessing objects from `_settings` or the internals of `Dry::Configurable::Config`. `_settings` now returns `Dry::Configurable::Setting` instances, which contain only the details from the setting's definition. Setting _values_ remain in `Dry::Configurable::Config`.
|
40
|
+
- Use Zeitwerk to speed up load time (#135 by @solnic)
|
41
|
+
|
42
|
+
[Compare v0.15.0...v0.16.0](https://github.com/dry-rb/dry-configurable/compare/v0.15.0...v0.16.0)
|
43
|
+
|
44
|
+
## 0.15.0 2022-04-21
|
45
|
+
|
46
|
+
|
47
|
+
### Changed
|
48
|
+
|
49
|
+
- The `finalize!` method (as class or instance method, depending on whether you extend or include `Dry::Configurable` respectively) now accepts a boolean `freeze_values:` argument, which if true, will recursively freeze all config values in addition to the `config` itself. (#105 by @ojab)
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class MyConfigurable
|
53
|
+
include Dry::Configurable
|
54
|
+
|
55
|
+
setting :db, default: "postgre"
|
56
|
+
end
|
57
|
+
|
58
|
+
my_obj = MyConfigurable.new
|
59
|
+
my_obj.finalize!(freeze_values: true)
|
60
|
+
my_obj.config.db << "sql" # Will raise FrozenError
|
61
|
+
```
|
62
|
+
- `Dry::Configurable::Config#update` will set hashes as values for non-nested settings (#131 by @ojab)
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
class MyConfigurable
|
66
|
+
extend Dry::Configurable
|
67
|
+
|
68
|
+
setting :sslcert, constructor: ->(v) { v&.values_at(:pem, :pass)&.join }
|
69
|
+
end
|
70
|
+
|
71
|
+
MyConfigurable.config.update(sslcert: {pem: "cert", pass: "qwerty"})
|
72
|
+
MyConfigurable.config.sslcert # => "certqwerty"
|
73
|
+
```
|
74
|
+
- `Dry::Configurable::Config#update` will accept any values implicitly convertible to hash via `#to_hash` (#133 by @timriley)
|
75
|
+
|
76
|
+
[Compare v0.14.0...v0.15.0](https://github.com/dry-rb/dry-configurable/compare/v0.14.0...v0.15.0)
|
77
|
+
|
78
|
+
## 0.14.0 2022-01-14
|
79
|
+
|
80
|
+
|
81
|
+
### Changed
|
82
|
+
|
83
|
+
- Settings defined after an access to `config` will still be made available on that `config`. (#130 by @timriley)
|
84
|
+
- Cloneable settings are cloned immediately upon assignment. (#130 by @timriley)
|
85
|
+
- Changes to config values in parent classes after subclasses have already been created will not be propogated to those subclasses. Subclasses created _after_ config values have been changed in the parent _will_ receive those config values. (#130 by @timriley)
|
86
|
+
|
87
|
+
[Compare v0.13.0...v0.14.0](https://github.com/dry-rb/dry-configurable/compare/v0.13.0...v0.14.0)
|
88
|
+
|
89
|
+
## 0.13.0 2021-09-12
|
90
|
+
|
91
|
+
|
92
|
+
### Added
|
93
|
+
|
94
|
+
- Added flags to determine whether to warn on the API usage deprecated in this release (see "Changed" section below). Set these to `false` to suppress the warnings. (#124 by @timriley)
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
Dry::Configurable.warn_on_setting_constructor_block false
|
98
|
+
Dry::Configurable.warn_on_setting_positional_default false
|
99
|
+
```
|
100
|
+
|
101
|
+
### Fixed
|
102
|
+
|
103
|
+
- Fixed `ArgumentError` for classes including `Dry::Configurable` whose `initializer` has required kwargs. (#113 by @timriley)
|
104
|
+
|
105
|
+
### Changed
|
106
|
+
|
107
|
+
- Deprecated the setting constructor provided as a block. Provide it via the `constructor:` keyword argument instead. (#111 by @waiting-for-dev & @timriley)
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
setting :path, constructor: -> path { Pathname(path) }
|
111
|
+
```
|
112
|
+
- Deprecated the setting default provided as the second positional argument. Provide it via the `default:` keyword argument instead. (#112 and #121 by @waiting-for-dev & @timriley)
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
setting :path, default: "some/default/path"
|
116
|
+
```
|
117
|
+
- [BREAKING] Removed implicit `to_hash` conversion from `Config`. (#114 by @timriley)
|
118
|
+
|
119
|
+
[Compare v0.12.1...v0.13.0](https://github.com/dry-rb/dry-configurable/compare/v0.12.1...v0.13.0)
|
120
|
+
|
3
121
|
## 0.12.1 2021-02-15
|
4
122
|
|
5
123
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
<!--- this file is synced from dry-rb/template-gem project -->
|
1
2
|
[gem]: https://rubygems.org/gems/dry-configurable
|
2
3
|
[actions]: https://github.com/dry-rb/dry-configurable/actions
|
3
4
|
[codacy]: https://www.codacy.com/gh/dry-rb/dry-configurable
|
@@ -10,19 +11,19 @@
|
|
10
11
|
[][actions]
|
11
12
|
[][codacy]
|
12
13
|
[][codacy]
|
13
|
-
[][inchpages]
|
14
15
|
|
15
16
|
## Links
|
16
17
|
|
17
|
-
* [User documentation](
|
18
|
+
* [User documentation](https://dry-rb.org/gems/dry-configurable)
|
18
19
|
* [API documentation](http://rubydoc.info/gems/dry-configurable)
|
19
20
|
|
20
21
|
## Supported Ruby versions
|
21
22
|
|
22
23
|
This library officially supports the following Ruby versions:
|
23
24
|
|
24
|
-
* MRI
|
25
|
-
* jruby
|
25
|
+
* MRI `>= 2.7.0`
|
26
|
+
* jruby `>= 9.3` (postponed until 2.7 is supported)
|
26
27
|
|
27
28
|
## License
|
28
29
|
|
data/dry-configurable.gemspec
CHANGED
@@ -1,35 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# this file is managed by dry-rb/devtools project
|
3
2
|
|
4
|
-
|
3
|
+
# this file is synced from dry-rb/template-gem project
|
4
|
+
|
5
|
+
lib = File.expand_path("lib", __dir__)
|
5
6
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
-
require
|
7
|
+
require "dry/configurable/version"
|
7
8
|
|
8
9
|
Gem::Specification.new do |spec|
|
9
|
-
spec.name =
|
10
|
+
spec.name = "dry-configurable"
|
10
11
|
spec.authors = ["Andy Holland"]
|
11
12
|
spec.email = ["andyholland1991@aol.com"]
|
12
|
-
spec.license =
|
13
|
+
spec.license = "MIT"
|
13
14
|
spec.version = Dry::Configurable::VERSION.dup
|
14
15
|
|
15
16
|
spec.summary = "A mixin to add configuration functionality to your classes"
|
16
17
|
spec.description = spec.summary
|
17
|
-
spec.homepage =
|
18
|
+
spec.homepage = "https://dry-rb.org/gems/dry-configurable"
|
18
19
|
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-configurable.gemspec", "lib/**/*"]
|
19
|
-
spec.bindir =
|
20
|
+
spec.bindir = "bin"
|
20
21
|
spec.executables = []
|
21
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ["lib"]
|
22
23
|
|
23
|
-
spec.metadata[
|
24
|
-
spec.metadata[
|
25
|
-
spec.metadata[
|
26
|
-
spec.metadata[
|
24
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-configurable/blob/main/CHANGELOG.md"
|
26
|
+
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-configurable"
|
27
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-configurable/issues"
|
27
28
|
|
28
|
-
spec.required_ruby_version = ">= 2.
|
29
|
+
spec.required_ruby_version = ">= 2.7.0"
|
29
30
|
|
30
31
|
# to update dependencies edit project.yml
|
31
|
-
spec.add_runtime_dependency "
|
32
|
-
spec.add_runtime_dependency "
|
32
|
+
spec.add_runtime_dependency "dry-core", "~> 0.6"
|
33
|
+
spec.add_runtime_dependency "zeitwerk", "~> 2.6"
|
33
34
|
|
34
35
|
spec.add_development_dependency "bundler"
|
35
36
|
spec.add_development_dependency "rake"
|
@@ -1,11 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require 'dry/configurable/constants'
|
6
|
-
require 'dry/configurable/dsl'
|
7
|
-
require 'dry/configurable/methods'
|
8
|
-
require 'dry/configurable/settings'
|
3
|
+
require "set"
|
9
4
|
|
10
5
|
module Dry
|
11
6
|
module Configurable
|
@@ -13,30 +8,40 @@ module Dry
|
|
13
8
|
include Methods
|
14
9
|
|
15
10
|
# @api private
|
16
|
-
def inherited(
|
11
|
+
def inherited(subclass)
|
17
12
|
super
|
18
13
|
|
19
|
-
|
14
|
+
subclass.instance_variable_set(:@__config_extension__, __config_extension__)
|
15
|
+
|
16
|
+
new_settings = _settings.dup
|
17
|
+
subclass.instance_variable_set(:@_settings, new_settings)
|
20
18
|
|
21
|
-
|
19
|
+
# Only classes **extending** Dry::Configurable have class-level config. When
|
20
|
+
# Dry::Configurable is **included**, the class-level config method is undefined because it
|
21
|
+
# resides at the instance-level instead (see `Configurable.included`).
|
22
|
+
if respond_to?(:config)
|
23
|
+
subclass.instance_variable_set(:@config, config.dup_for_settings(new_settings))
|
24
|
+
end
|
22
25
|
end
|
23
26
|
|
24
27
|
# Add a setting to the configuration
|
25
28
|
#
|
26
|
-
# @param [Mixed]
|
29
|
+
# @param [Mixed] name
|
27
30
|
# The accessor key for the configuration value
|
28
31
|
# @param [Mixed] default
|
29
|
-
#
|
30
|
-
#
|
32
|
+
# Default value for the setting
|
33
|
+
# @param [#call] constructor
|
34
|
+
# Transformation given value will go through
|
35
|
+
# @param [Boolean] reader
|
36
|
+
# Whether a reader accessor must be created
|
31
37
|
# @yield
|
32
|
-
#
|
33
|
-
# a new configuration class, and bound as the default value
|
38
|
+
# A block can be given to add nested settings.
|
34
39
|
#
|
35
40
|
# @return [Dry::Configurable::Config]
|
36
41
|
#
|
37
42
|
# @api public
|
38
|
-
def setting(*args, &block)
|
39
|
-
setting = __config_dsl__.setting(*args, &block)
|
43
|
+
def setting(*args, **options, &block)
|
44
|
+
setting = __config_dsl__.setting(*args, **options, &block)
|
40
45
|
|
41
46
|
_settings << setting
|
42
47
|
|
@@ -51,7 +56,7 @@ module Dry
|
|
51
56
|
#
|
52
57
|
# @api public
|
53
58
|
def settings
|
54
|
-
|
59
|
+
Set[*_settings.map(&:name)]
|
55
60
|
end
|
56
61
|
|
57
62
|
# Return declared settings
|
@@ -69,12 +74,25 @@ module Dry
|
|
69
74
|
#
|
70
75
|
# @api public
|
71
76
|
def config
|
72
|
-
@config ||=
|
77
|
+
@config ||= __config_build__
|
78
|
+
end
|
79
|
+
|
80
|
+
# @api private
|
81
|
+
def __config_build__(settings = _settings)
|
82
|
+
__config_extension__.config_class.new(settings)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
def __config_extension__
|
87
|
+
@__config_extension__
|
73
88
|
end
|
74
89
|
|
75
90
|
# @api private
|
76
91
|
def __config_dsl__
|
77
|
-
@
|
92
|
+
@__config_dsl__ ||= DSL.new(
|
93
|
+
config_class: __config_extension__.config_class,
|
94
|
+
default_undefined: __config_extension__.default_undefined
|
95
|
+
)
|
78
96
|
end
|
79
97
|
|
80
98
|
# @api private
|
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/configurable/setting'
|
4
|
-
require 'dry/configurable/settings'
|
5
|
-
|
6
3
|
module Dry
|
7
4
|
module Configurable
|
8
5
|
# Setting compiler used internally by the DSL
|
@@ -23,22 +20,18 @@ module Dry
|
|
23
20
|
public_send(:"visit_#{type}", rest)
|
24
21
|
end
|
25
22
|
|
26
|
-
# @api private
|
27
|
-
def visit_constructor(node)
|
28
|
-
setting, constructor = node
|
29
|
-
visit(setting).with(constructor: constructor)
|
30
|
-
end
|
31
|
-
|
32
23
|
# @api private
|
33
24
|
def visit_setting(node)
|
34
|
-
name,
|
35
|
-
Setting.new(name, **opts
|
25
|
+
name, opts = node
|
26
|
+
Setting.new(name, **opts)
|
36
27
|
end
|
37
28
|
|
38
29
|
# @api private
|
39
30
|
def visit_nested(node)
|
40
31
|
parent, children = node
|
41
|
-
|
32
|
+
name, opts = parent[1]
|
33
|
+
|
34
|
+
Setting.new(name, **opts, children: Settings.new(call(children)))
|
42
35
|
end
|
43
36
|
end
|
44
37
|
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/core/constants"
|
4
|
+
require "set"
|
4
5
|
|
5
|
-
require
|
6
|
-
|
7
|
-
require 'dry/configurable/constants'
|
8
|
-
require 'dry/configurable/errors'
|
6
|
+
require "dry/core/equalizer"
|
9
7
|
|
10
8
|
module Dry
|
11
9
|
module Configurable
|
@@ -19,12 +17,29 @@ module Dry
|
|
19
17
|
attr_reader :_settings
|
20
18
|
|
21
19
|
# @api private
|
22
|
-
attr_reader :
|
20
|
+
attr_reader :_values
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
attr_reader :_configured
|
24
|
+
protected :_configured
|
23
25
|
|
24
26
|
# @api private
|
25
|
-
def initialize(settings)
|
26
|
-
@_settings = settings
|
27
|
-
@
|
27
|
+
def initialize(settings, values: {})
|
28
|
+
@_settings = settings
|
29
|
+
@_values = values
|
30
|
+
@_configured = Set.new
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
private def initialize_copy(source)
|
35
|
+
super
|
36
|
+
@_values = source.__send__(:dup_values)
|
37
|
+
@_configured = source._configured.dup
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def dup_for_settings(settings)
|
42
|
+
dup.tap { |config| config.instance_variable_set(:@_settings, settings) }
|
28
43
|
end
|
29
44
|
|
30
45
|
# Get config value by a key
|
@@ -34,9 +49,19 @@ module Dry
|
|
34
49
|
# @return Config value
|
35
50
|
def [](name)
|
36
51
|
name = name.to_sym
|
37
|
-
raise ArgumentError, "+#{name}+ is not a setting name" unless _settings.key?(name)
|
38
52
|
|
39
|
-
_settings[name]
|
53
|
+
unless (setting = _settings[name])
|
54
|
+
raise ArgumentError, "+#{name}+ is not a setting name"
|
55
|
+
end
|
56
|
+
|
57
|
+
_values.fetch(name) {
|
58
|
+
# Mutable settings may be configured after read
|
59
|
+
_configured.add(name) if setting.cloneable?
|
60
|
+
|
61
|
+
setting.to_value.tap { |value|
|
62
|
+
_values[name] = value
|
63
|
+
}
|
64
|
+
}
|
40
65
|
end
|
41
66
|
|
42
67
|
# Set config value.
|
@@ -45,21 +70,34 @@ module Dry
|
|
45
70
|
# @param [String,Symbol] name
|
46
71
|
# @param [Object] value
|
47
72
|
def []=(name, value)
|
48
|
-
|
73
|
+
raise FrozenConfig, "Cannot modify frozen config" if frozen?
|
74
|
+
|
75
|
+
name = name.to_sym
|
76
|
+
|
77
|
+
unless (setting = _settings[name])
|
78
|
+
raise ArgumentError, "+#{name}+ is not a setting name"
|
79
|
+
end
|
80
|
+
|
81
|
+
_configured.add(name)
|
82
|
+
|
83
|
+
_values[name] = setting.constructor.(value)
|
49
84
|
end
|
50
85
|
|
51
86
|
# Update config with new values
|
52
87
|
#
|
53
|
-
# @param values [Hash] A hash with new values
|
88
|
+
# @param values [Hash, #to_hash] A hash with new values
|
54
89
|
#
|
55
90
|
# @return [Config]
|
56
91
|
#
|
57
92
|
# @api public
|
58
93
|
def update(values)
|
59
94
|
values.each do |key, value|
|
60
|
-
|
61
|
-
|
62
|
-
|
95
|
+
if self[key].is_a?(self.class)
|
96
|
+
unless value.respond_to?(:to_hash)
|
97
|
+
raise ArgumentError, "#{value.inspect} is not a valid setting value"
|
98
|
+
end
|
99
|
+
|
100
|
+
self[key].update(value.to_hash)
|
63
101
|
else
|
64
102
|
self[key] = value
|
65
103
|
end
|
@@ -67,62 +105,94 @@ module Dry
|
|
67
105
|
self
|
68
106
|
end
|
69
107
|
|
70
|
-
#
|
108
|
+
# Returns true if the value for the given key has been set on this config.
|
109
|
+
#
|
110
|
+
# For simple values, this returns true if the value has been explicitly assigned.
|
111
|
+
#
|
112
|
+
# For cloneable (mutable) values, since these are captured on read, returns true if the value
|
113
|
+
# does not compare equally to its corresdponing default value. This relies on these objects
|
114
|
+
# having functioning `#==` checks.
|
115
|
+
#
|
116
|
+
# @return [Bool]
|
117
|
+
#
|
118
|
+
# @api public
|
119
|
+
def configured?(key)
|
120
|
+
if _configured.include?(key) && _settings[key].cloneable?
|
121
|
+
return _values[key] != _settings[key].to_value
|
122
|
+
end
|
123
|
+
|
124
|
+
_configured.include?(key)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns the current config values.
|
128
|
+
#
|
129
|
+
# Nested configs remain in their {Config} instances.
|
71
130
|
#
|
72
131
|
# @return [Hash]
|
73
132
|
#
|
74
133
|
# @api public
|
75
134
|
def values
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
135
|
+
# Ensure all settings are represented in values
|
136
|
+
_settings.each { |setting| self[setting.name] unless _values.key?(setting.name) }
|
137
|
+
|
138
|
+
_values
|
80
139
|
end
|
81
|
-
alias_method :to_h, :values
|
82
|
-
alias_method :to_hash, :values
|
83
140
|
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
141
|
+
# Returns config values as a hash, with nested values also converted from {Config} instances
|
142
|
+
# into hashes.
|
143
|
+
#
|
144
|
+
# @return [Hash]
|
145
|
+
#
|
146
|
+
# @api public
|
147
|
+
def to_h
|
148
|
+
values.to_h { |key, value| [key, value.is_a?(self.class) ? value.to_h : value] }
|
88
149
|
end
|
89
150
|
|
90
151
|
# @api private
|
91
|
-
def
|
92
|
-
|
152
|
+
def finalize!(freeze_values: false)
|
153
|
+
values.each_value do |value|
|
154
|
+
if value.is_a?(self.class)
|
155
|
+
value.finalize!(freeze_values: freeze_values)
|
156
|
+
elsif freeze_values
|
157
|
+
value.freeze
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
freeze
|
93
162
|
end
|
94
163
|
|
95
164
|
# @api private
|
96
|
-
def
|
97
|
-
|
165
|
+
def pristine
|
166
|
+
self.class.new(_settings)
|
98
167
|
end
|
99
168
|
|
100
169
|
private
|
101
170
|
|
102
|
-
|
103
|
-
|
104
|
-
setting = _settings[
|
171
|
+
def method_missing(name, *args)
|
172
|
+
setting_name = setting_name_from_method(name)
|
173
|
+
setting = _settings[setting_name]
|
105
174
|
|
106
175
|
super unless setting
|
107
176
|
|
108
|
-
if
|
109
|
-
|
110
|
-
|
111
|
-
_settings << setting.with(input: args[0])
|
177
|
+
if name.end_with?("=")
|
178
|
+
self[setting_name] = args[0]
|
112
179
|
else
|
113
|
-
|
180
|
+
self[setting_name]
|
114
181
|
end
|
115
182
|
end
|
116
183
|
|
117
|
-
|
118
|
-
|
119
|
-
_resolved.fetch(meth) { _resolved[meth] = meth.to_s.tr('=', '').to_sym }
|
184
|
+
def respond_to_missing?(meth, include_private = false)
|
185
|
+
_settings.key?(setting_name_from_method(meth)) || super
|
120
186
|
end
|
121
187
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
188
|
+
def setting_name_from_method(method_name)
|
189
|
+
method_name.to_s.tr("=", "").to_sym
|
190
|
+
end
|
191
|
+
|
192
|
+
def dup_values
|
193
|
+
_values.each_with_object({}) { |(key, val), dup_hsh|
|
194
|
+
dup_hsh[key] = _settings[key].cloneable? ? val.dup : val
|
195
|
+
}
|
126
196
|
end
|
127
197
|
end
|
128
198
|
end
|
data/lib/dry/configurable/dsl.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'dry/configurable/setting'
|
5
|
-
require 'dry/configurable/settings'
|
6
|
-
require 'dry/configurable/compiler'
|
7
|
-
require 'dry/configurable/dsl/args'
|
3
|
+
require "dry/core/deprecations"
|
8
4
|
|
9
5
|
module Dry
|
10
6
|
module Configurable
|
@@ -14,49 +10,67 @@ module Dry
|
|
14
10
|
class DSL
|
15
11
|
VALID_NAME = /\A[a-z_]\w*\z/i.freeze
|
16
12
|
|
17
|
-
# @api private
|
18
13
|
attr_reader :compiler
|
19
14
|
|
20
|
-
# @api private
|
21
15
|
attr_reader :ast
|
22
16
|
|
23
|
-
|
24
|
-
|
17
|
+
attr_reader :options
|
18
|
+
|
19
|
+
def initialize(**options, &block)
|
25
20
|
@compiler = Compiler.new
|
26
21
|
@ast = []
|
22
|
+
@options = options
|
27
23
|
instance_exec(&block) if block
|
28
24
|
end
|
29
25
|
|
30
|
-
#
|
26
|
+
# Registers a new setting node and compile it into a setting object
|
31
27
|
#
|
32
28
|
# @see ClassMethods.setting
|
33
|
-
# @api
|
29
|
+
# @api private
|
34
30
|
# @return Setting
|
35
|
-
def setting(name,
|
31
|
+
def setting(name, **options, &block) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
36
32
|
unless VALID_NAME.match?(name.to_s)
|
37
33
|
raise ArgumentError, "#{name} is not a valid setting name"
|
38
34
|
end
|
39
35
|
|
40
|
-
|
36
|
+
ensure_valid_options(options)
|
41
37
|
|
42
|
-
|
38
|
+
options = {default: default, config_class: config_class, **options}
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
node = [:setting, [name.to_sym, default, opts == default ? EMPTY_HASH : opts]]
|
40
|
+
node = [:setting, [name.to_sym, options]]
|
47
41
|
|
48
42
|
if block
|
49
|
-
|
50
|
-
ast << [:nested, [node, DSL.new(&block).ast]]
|
51
|
-
else
|
52
|
-
ast << [:constructor, [node, block]]
|
53
|
-
end
|
43
|
+
ast << [:nested, [node, DSL.new(&block).ast]]
|
54
44
|
else
|
55
45
|
ast << node
|
56
46
|
end
|
57
47
|
|
58
48
|
compiler.visit(ast.last)
|
59
49
|
end
|
50
|
+
|
51
|
+
def config_class
|
52
|
+
options[:config_class]
|
53
|
+
end
|
54
|
+
|
55
|
+
def default
|
56
|
+
options[:default_undefined] ? Undefined : nil
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def ensure_valid_options(options)
|
62
|
+
return if options.none?
|
63
|
+
|
64
|
+
invalid_keys = options.keys - Setting::OPTIONS
|
65
|
+
|
66
|
+
raise ArgumentError, "Invalid options: #{invalid_keys.inspect}" unless invalid_keys.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns a tuple of valid and invalid options hashes derived from the options hash
|
70
|
+
# given to the setting
|
71
|
+
def valid_and_invalid_options(options)
|
72
|
+
options.partition { |k, _| Setting::OPTIONS.include?(k) }.map(&:to_h)
|
73
|
+
end
|
60
74
|
end
|
61
75
|
end
|
62
76
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Configurable
|
5
|
+
class Extension < Module
|
6
|
+
# @api private
|
7
|
+
attr_reader :config_class
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
attr_reader :default_undefined
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
def initialize(config_class: Configurable::Config, default_undefined: false)
|
14
|
+
super()
|
15
|
+
@config_class = config_class
|
16
|
+
@default_undefined = default_undefined
|
17
|
+
freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def extended(klass)
|
22
|
+
super
|
23
|
+
klass.extend(ClassMethods)
|
24
|
+
klass.instance_variable_set(:@__config_extension__, self)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
def included(klass)
|
29
|
+
raise AlreadyIncluded if klass.include?(InstanceMethods)
|
30
|
+
|
31
|
+
super
|
32
|
+
|
33
|
+
klass.class_eval do
|
34
|
+
extend(ClassMethods)
|
35
|
+
include(InstanceMethods)
|
36
|
+
prepend(Initializer)
|
37
|
+
|
38
|
+
class << self
|
39
|
+
undef :config
|
40
|
+
undef :configure
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
klass.instance_variable_set(:@__config_extension__, self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "dry/configurable/config"
|
4
|
+
require "dry/configurable/methods"
|
5
5
|
|
6
6
|
module Dry
|
7
7
|
module Configurable
|
@@ -12,9 +12,11 @@ module Dry
|
|
12
12
|
module Initializer
|
13
13
|
# @api private
|
14
14
|
def initialize(*)
|
15
|
-
@config =
|
15
|
+
@config = self.class.__config_build__(self.class._settings)
|
16
|
+
|
16
17
|
super
|
17
18
|
end
|
19
|
+
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
18
20
|
end
|
19
21
|
|
20
22
|
# Instance-level API when `Dry::Configurable` is included in a class
|
@@ -33,9 +35,7 @@ module Dry
|
|
33
35
|
# Finalize the config and freeze the object
|
34
36
|
#
|
35
37
|
# @api public
|
36
|
-
def finalize!
|
37
|
-
return self if frozen?
|
38
|
-
|
38
|
+
def finalize!(freeze_values: false)
|
39
39
|
super
|
40
40
|
freeze
|
41
41
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/configurable/errors'
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
module Configurable
|
7
5
|
# Common API for both classes and instances
|
@@ -10,7 +8,7 @@ module Dry
|
|
10
8
|
module Methods
|
11
9
|
# @api public
|
12
10
|
def configure(&block)
|
13
|
-
raise FrozenConfig,
|
11
|
+
raise FrozenConfig, "Cannot modify frozen config" if frozen?
|
14
12
|
|
15
13
|
yield(config) if block
|
16
14
|
self
|
@@ -21,10 +19,8 @@ module Dry
|
|
21
19
|
# @return [Dry::Configurable::Config]
|
22
20
|
#
|
23
21
|
# @api public
|
24
|
-
def finalize!
|
25
|
-
|
26
|
-
|
27
|
-
config.finalize!
|
22
|
+
def finalize!(freeze_values: false)
|
23
|
+
config.finalize!(freeze_values: freeze_values)
|
28
24
|
self
|
29
25
|
end
|
30
26
|
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "set"
|
4
4
|
|
5
|
-
require
|
6
|
-
|
7
|
-
require 'dry/configurable/constants'
|
8
|
-
require 'dry/configurable/config'
|
5
|
+
require "dry/core/equalizer"
|
9
6
|
|
10
7
|
module Dry
|
11
8
|
module Configurable
|
@@ -13,9 +10,9 @@ module Dry
|
|
13
10
|
#
|
14
11
|
# @api private
|
15
12
|
class Setting
|
16
|
-
include Dry::Equalizer(:name, :
|
13
|
+
include Dry::Equalizer(:name, :default, :constructor, :children, :options, inspect: false)
|
17
14
|
|
18
|
-
OPTIONS = %i[
|
15
|
+
OPTIONS = %i[default reader constructor cloneable settings config_class].freeze
|
19
16
|
|
20
17
|
DEFAULT_CONSTRUCTOR = -> v { v }.freeze
|
21
18
|
|
@@ -25,33 +22,19 @@ module Dry
|
|
25
22
|
attr_reader :name
|
26
23
|
|
27
24
|
# @api private
|
28
|
-
attr_reader :
|
25
|
+
attr_reader :default
|
29
26
|
|
30
27
|
# @api private
|
31
|
-
attr_reader :
|
28
|
+
attr_reader :cloneable
|
32
29
|
|
33
30
|
# @api private
|
34
|
-
attr_reader :
|
31
|
+
attr_reader :constructor
|
35
32
|
|
36
33
|
# @api private
|
37
|
-
attr_reader :
|
34
|
+
attr_reader :children
|
38
35
|
|
39
|
-
# Specialized Setting which includes nested settings
|
40
|
-
#
|
41
36
|
# @api private
|
42
|
-
|
43
|
-
CONSTRUCTOR = Config.method(:new)
|
44
|
-
|
45
|
-
# @api private
|
46
|
-
def pristine
|
47
|
-
with(input: input.pristine)
|
48
|
-
end
|
49
|
-
|
50
|
-
# @api private
|
51
|
-
def constructor
|
52
|
-
CONSTRUCTOR
|
53
|
-
end
|
54
|
-
end
|
37
|
+
attr_reader :options
|
55
38
|
|
56
39
|
# @api private
|
57
40
|
def self.cloneable_value?(value)
|
@@ -59,49 +42,21 @@ module Dry
|
|
59
42
|
end
|
60
43
|
|
61
44
|
# @api private
|
62
|
-
def initialize(
|
45
|
+
def initialize(
|
46
|
+
name,
|
47
|
+
default:,
|
48
|
+
constructor: DEFAULT_CONSTRUCTOR,
|
49
|
+
children: EMPTY_ARRAY,
|
50
|
+
**options
|
51
|
+
)
|
63
52
|
@name = name
|
64
|
-
@writer_name = :"#{name}="
|
65
|
-
@input = input
|
66
53
|
@default = default
|
54
|
+
@cloneable = children.any? || options.fetch(:cloneable) {
|
55
|
+
Setting.cloneable_value?(default)
|
56
|
+
}
|
57
|
+
@constructor = constructor
|
58
|
+
@children = children
|
67
59
|
@options = options
|
68
|
-
|
69
|
-
evaluate if input_defined?
|
70
|
-
end
|
71
|
-
|
72
|
-
# @api private
|
73
|
-
def input_defined?
|
74
|
-
!input.equal?(Undefined)
|
75
|
-
end
|
76
|
-
|
77
|
-
# @api private
|
78
|
-
def value
|
79
|
-
@value ||= evaluate
|
80
|
-
end
|
81
|
-
|
82
|
-
# @api private
|
83
|
-
def evaluated?
|
84
|
-
instance_variable_defined?(:@value)
|
85
|
-
end
|
86
|
-
|
87
|
-
# @api private
|
88
|
-
def nested(settings)
|
89
|
-
Nested.new(name, input: settings, **options)
|
90
|
-
end
|
91
|
-
|
92
|
-
# @api private
|
93
|
-
def pristine
|
94
|
-
with(input: Undefined)
|
95
|
-
end
|
96
|
-
|
97
|
-
# @api private
|
98
|
-
def with(new_opts)
|
99
|
-
self.class.new(name, input: input, default: default, **options, **new_opts)
|
100
|
-
end
|
101
|
-
|
102
|
-
# @api private
|
103
|
-
def constructor
|
104
|
-
options[:constructor] || DEFAULT_CONSTRUCTOR
|
105
60
|
end
|
106
61
|
|
107
62
|
# @api private
|
@@ -109,43 +64,22 @@ module Dry
|
|
109
64
|
options[:reader].equal?(true)
|
110
65
|
end
|
111
66
|
|
112
|
-
# @api private
|
113
|
-
def writer?(meth)
|
114
|
-
writer_name.equal?(meth)
|
115
|
-
end
|
116
|
-
|
117
67
|
# @api private
|
118
68
|
def cloneable?
|
119
|
-
|
120
|
-
# Return cloneable option if explicitly set
|
121
|
-
options[:cloneable]
|
122
|
-
else
|
123
|
-
# Otherwise, infer cloneable from any of the input, default, or value
|
124
|
-
Setting.cloneable_value?(input) || Setting.cloneable_value?(default) || (
|
125
|
-
evaluated? && Setting.cloneable_value?(value)
|
126
|
-
)
|
127
|
-
end
|
69
|
+
cloneable
|
128
70
|
end
|
129
71
|
|
130
|
-
private
|
131
|
-
|
132
72
|
# @api private
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
73
|
+
def to_value
|
74
|
+
if children.any?
|
75
|
+
(options[:config_class] || Config).new(children)
|
76
|
+
else
|
77
|
+
value = default
|
78
|
+
value = constructor.(value) unless value.eql?(Undefined)
|
137
79
|
|
138
|
-
|
139
|
-
@input = source.input.dup
|
140
|
-
@default = source.default.dup
|
141
|
-
@value = source.value.dup if source.evaluated?
|
80
|
+
cloneable? ? value.dup : value
|
142
81
|
end
|
143
82
|
end
|
144
|
-
|
145
|
-
# @api private
|
146
|
-
def evaluate
|
147
|
-
@value = constructor[Undefined.coalesce(input, default, nil)]
|
148
|
-
end
|
149
83
|
end
|
150
84
|
end
|
151
85
|
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require 'dry/core/equalizer'
|
6
|
-
require 'dry/configurable/constants'
|
3
|
+
require "dry/core/equalizer"
|
7
4
|
|
8
5
|
module Dry
|
9
6
|
module Configurable
|
@@ -11,27 +8,27 @@ module Dry
|
|
11
8
|
#
|
12
9
|
# @api private
|
13
10
|
class Settings
|
14
|
-
include Dry::Equalizer(:
|
11
|
+
include Dry::Equalizer(:settings)
|
15
12
|
|
16
13
|
include Enumerable
|
17
14
|
|
18
15
|
# @api private
|
19
|
-
attr_reader :
|
16
|
+
attr_reader :settings
|
20
17
|
|
21
18
|
# @api private
|
22
|
-
def initialize(
|
23
|
-
|
19
|
+
def initialize(settings = EMPTY_ARRAY)
|
20
|
+
@settings = settings.each_with_object({}) { |s, m| m[s.name] = s }
|
24
21
|
end
|
25
22
|
|
26
23
|
# @api private
|
27
24
|
def <<(setting)
|
28
|
-
|
25
|
+
settings[setting.name] = setting
|
29
26
|
self
|
30
27
|
end
|
31
28
|
|
32
29
|
# @api private
|
33
30
|
def [](name)
|
34
|
-
|
31
|
+
settings[name]
|
35
32
|
end
|
36
33
|
|
37
34
|
# @api private
|
@@ -41,31 +38,18 @@ module Dry
|
|
41
38
|
|
42
39
|
# @api private
|
43
40
|
def keys
|
44
|
-
|
41
|
+
settings.keys
|
45
42
|
end
|
46
43
|
|
47
44
|
# @api private
|
48
45
|
def each(&block)
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
# @api private
|
53
|
-
def pristine
|
54
|
-
self.class.new(map(&:pristine))
|
46
|
+
settings.each_value(&block)
|
55
47
|
end
|
56
48
|
|
57
49
|
private
|
58
50
|
|
59
|
-
# @api private
|
60
51
|
def initialize_copy(source)
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
# @api private
|
65
|
-
def initialize_elements(elements)
|
66
|
-
@elements = elements.each_with_object(Concurrent::Map.new) { |s, m|
|
67
|
-
m[s.name] = s
|
68
|
-
}
|
52
|
+
@settings = source.settings.dup
|
69
53
|
end
|
70
54
|
end
|
71
55
|
end
|
data/lib/dry/configurable.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "zeitwerk"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require 'dry/configurable/config'
|
9
|
-
require 'dry/configurable/setting'
|
10
|
-
require 'dry/configurable/errors'
|
5
|
+
require "dry/core/constants"
|
6
|
+
require "dry/configurable/constants"
|
7
|
+
require "dry/configurable/errors"
|
11
8
|
|
12
9
|
module Dry
|
10
|
+
# @api public
|
11
|
+
def self.Configurable(**options)
|
12
|
+
Configurable::Extension.new(**options)
|
13
|
+
end
|
14
|
+
|
13
15
|
# A simple configuration mixin
|
14
16
|
#
|
15
17
|
# @example class-level configuration
|
@@ -44,27 +46,32 @@ module Dry
|
|
44
46
|
#
|
45
47
|
# @api public
|
46
48
|
module Configurable
|
49
|
+
def self.loader
|
50
|
+
@loader ||= Zeitwerk::Loader.new.tap do |loader|
|
51
|
+
root = File.expand_path("..", __dir__)
|
52
|
+
loader.tag = "dry-configurable"
|
53
|
+
loader.inflector = Zeitwerk::GemInflector.new("#{root}/dry-configurable.rb")
|
54
|
+
loader.push_dir(root)
|
55
|
+
loader.ignore(
|
56
|
+
"#{root}/dry-configurable.rb",
|
57
|
+
"#{root}/dry/configurable/{constants,errors,version}.rb"
|
58
|
+
)
|
59
|
+
loader.inflector.inflect("dsl" => "DSL")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
47
63
|
# @api private
|
48
64
|
def self.extended(klass)
|
49
65
|
super
|
50
|
-
klass.extend(
|
66
|
+
klass.extend(Extension.new)
|
51
67
|
end
|
52
68
|
|
53
69
|
# @api private
|
54
70
|
def self.included(klass)
|
55
|
-
raise AlreadyIncluded if klass.include?(InstanceMethods)
|
56
|
-
|
57
71
|
super
|
58
|
-
klass.
|
59
|
-
extend(ClassMethods)
|
60
|
-
include(InstanceMethods)
|
61
|
-
prepend(Initializer)
|
62
|
-
|
63
|
-
class << self
|
64
|
-
undef :config
|
65
|
-
undef :configure
|
66
|
-
end
|
67
|
-
end
|
72
|
+
klass.include(Extension.new)
|
68
73
|
end
|
74
|
+
|
75
|
+
loader.setup
|
69
76
|
end
|
70
77
|
end
|
data/lib/dry-configurable.rb
CHANGED
metadata
CHANGED
@@ -1,49 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-configurable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Holland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: dry-core
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0.6'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: zeitwerk
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
- - ">="
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 0.5.0
|
33
|
+
version: '2.6'
|
37
34
|
type: :runtime
|
38
35
|
prerelease: false
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
40
37
|
requirements:
|
41
38
|
- - "~>"
|
42
39
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 0.5.0
|
40
|
+
version: '2.6'
|
47
41
|
- !ruby/object:Gem::Dependency
|
48
42
|
name: bundler
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,8 +98,8 @@ files:
|
|
104
98
|
- lib/dry/configurable/config.rb
|
105
99
|
- lib/dry/configurable/constants.rb
|
106
100
|
- lib/dry/configurable/dsl.rb
|
107
|
-
- lib/dry/configurable/dsl/args.rb
|
108
101
|
- lib/dry/configurable/errors.rb
|
102
|
+
- lib/dry/configurable/extension.rb
|
109
103
|
- lib/dry/configurable/instance_methods.rb
|
110
104
|
- lib/dry/configurable/methods.rb
|
111
105
|
- lib/dry/configurable/setting.rb
|
@@ -117,7 +111,7 @@ licenses:
|
|
117
111
|
- MIT
|
118
112
|
metadata:
|
119
113
|
allowed_push_host: https://rubygems.org
|
120
|
-
changelog_uri: https://github.com/dry-rb/dry-configurable/blob/
|
114
|
+
changelog_uri: https://github.com/dry-rb/dry-configurable/blob/main/CHANGELOG.md
|
121
115
|
source_code_uri: https://github.com/dry-rb/dry-configurable
|
122
116
|
bug_tracker_uri: https://github.com/dry-rb/dry-configurable/issues
|
123
117
|
post_install_message:
|
@@ -128,14 +122,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
122
|
requirements:
|
129
123
|
- - ">="
|
130
124
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.
|
125
|
+
version: 2.7.0
|
132
126
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
127
|
requirements:
|
134
128
|
- - ">="
|
135
129
|
- !ruby/object:Gem::Version
|
136
130
|
version: '0'
|
137
131
|
requirements: []
|
138
|
-
rubygems_version: 3.1.
|
132
|
+
rubygems_version: 3.1.6
|
139
133
|
signing_key:
|
140
134
|
specification_version: 4
|
141
135
|
summary: A mixin to add configuration functionality to your classes
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'dry/configurable/constants'
|
4
|
-
require 'dry/configurable/setting'
|
5
|
-
|
6
|
-
module Dry
|
7
|
-
module Configurable
|
8
|
-
class DSL
|
9
|
-
# @api private
|
10
|
-
class Args
|
11
|
-
# @api private
|
12
|
-
attr_reader :args
|
13
|
-
|
14
|
-
# @api private
|
15
|
-
attr_reader :size
|
16
|
-
|
17
|
-
# @api private
|
18
|
-
attr_reader :opts
|
19
|
-
|
20
|
-
# @api private
|
21
|
-
def initialize(args)
|
22
|
-
@args = args
|
23
|
-
@size = args.size
|
24
|
-
@opts = Setting::OPTIONS
|
25
|
-
end
|
26
|
-
|
27
|
-
# @api private
|
28
|
-
def ensure_valid_options
|
29
|
-
return unless options
|
30
|
-
|
31
|
-
keys = options.keys - opts
|
32
|
-
raise ArgumentError, "Invalid options: #{keys.inspect}" unless keys.empty?
|
33
|
-
end
|
34
|
-
|
35
|
-
# @api private
|
36
|
-
def to_ary
|
37
|
-
[default, options || EMPTY_HASH]
|
38
|
-
end
|
39
|
-
|
40
|
-
# @api private
|
41
|
-
def default
|
42
|
-
if size.equal?(1) && options.nil?
|
43
|
-
args[0]
|
44
|
-
elsif size > 1 && options
|
45
|
-
args[0]
|
46
|
-
else
|
47
|
-
Undefined
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# @api private
|
52
|
-
def options
|
53
|
-
args.detect { |arg| arg.is_a?(Hash) && (opts & arg.keys).any? }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|