dry-configurable 0.11.6 → 0.13.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/CHANGELOG.md +82 -2
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/dry-configurable.gemspec +15 -15
- data/lib/dry/configurable/class_methods.rb +16 -14
- data/lib/dry/configurable/compiler.rb +4 -10
- data/lib/dry/configurable/config.rb +6 -7
- data/lib/dry/configurable/constants.rb +1 -1
- data/lib/dry/configurable/dsl.rb +119 -17
- data/lib/dry/configurable/flags.rb +19 -0
- data/lib/dry/configurable/instance_methods.rb +15 -8
- data/lib/dry/configurable/methods.rb +2 -2
- data/lib/dry/configurable/setting.rb +30 -11
- data/lib/dry/configurable/settings.rb +3 -3
- data/lib/dry/configurable/version.rb +1 -1
- data/lib/dry/configurable.rb +8 -7
- data/lib/dry-configurable.rb +1 -1
- metadata +7 -27
- 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: 0b1292743d03212bcca735f18e876046b27cb3859a561a9b714704627542a324
|
4
|
+
data.tar.gz: 5d9f334008b7d055bbcbadf21feb61dbef8888ed01cc877e54cd7f5959b46f48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b9bbe538bd93cc27e87e7e97a83bd1f98757d776d215028b88bb8d8b085a2114c53b7f4e3ad1d77ae70b21d99652a7bbe65d978106f897e784374456cb615db
|
7
|
+
data.tar.gz: 9fdeb06faf9888965037a364560c10364342731e7c825d56d4fd1cdeeb929992e201ef1f6fb3b14d4fb68ee037588e3a064a8f2236588d0417599e55df7a6a89
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,84 @@
|
|
1
|
-
|
1
|
+
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
|
+
|
3
|
+
## 0.13.0 2021-09-12
|
4
|
+
|
5
|
+
|
6
|
+
### Added
|
7
|
+
|
8
|
+
- 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)
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
Dry::Configurable.warn_on_setting_constructor_block = false
|
12
|
+
Dry::Configurable.warn_on_setting_positional_default = false
|
13
|
+
```
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
|
17
|
+
- Fixed `ArgumentError` for classes including `Dry::Configurable` whose `initializer` has required kwargs. (#113 by @timriley)
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
|
21
|
+
- Deprecated the setting constructor provided as a block. Provide it via the `constructor:` keyword argument instead. (#111 by @waiting-for-dev & @timriley)
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
setting :path, constructor: -> path { Pathname(path) }
|
25
|
+
```
|
26
|
+
- 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)
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
setting :path, default: "some/default/path"
|
30
|
+
```
|
31
|
+
- [BREAKING] Removed implicit `to_hash` conversion from `Config`. (#114 by @timriley)
|
32
|
+
|
33
|
+
[Compare v0.12.1...v0.13.0](https://github.com/dry-rb/dry-configurable/compare/v0.12.1...v0.13.0)
|
34
|
+
|
35
|
+
## 0.12.1 2021-02-15
|
36
|
+
|
37
|
+
|
38
|
+
### Added
|
39
|
+
|
40
|
+
- Settings may be specified with a `cloneable` option, e.g.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
setting :component_dirs, Configuration::ComponentDirs.new, cloneable: true
|
44
|
+
```
|
45
|
+
|
46
|
+
This change makes it possible to provide “rich” config values that carry their own
|
47
|
+
configuration interface.
|
48
|
+
|
49
|
+
In the above example, `ComponentDirs` could provide its own API for adding component
|
50
|
+
dirs and configuring aspects of their behavior at the same time. By being passed to
|
51
|
+
the setting along with `cloneable: true`, dry-configurable will ensure the setting's
|
52
|
+
values are cloned along with the setting at all the appropriate times.
|
53
|
+
|
54
|
+
A custom cloneable setting value should provide its own `#initialize_copy` (used by
|
55
|
+
`Object#dup`) with the appropriate logic. (@timriley in #102)
|
56
|
+
|
57
|
+
### Fixed
|
58
|
+
|
59
|
+
- Only `#initialize` instance method is prepended, leaving the rest of the instance
|
60
|
+
methods to be included as normal again. This allows classes including
|
61
|
+
`Dry::Configurable` to override instance methods with their own methods as required
|
62
|
+
(@adam12 in #103)
|
63
|
+
|
64
|
+
|
65
|
+
[Compare v0.12.0...v0.12.1](https://github.com/dry-rb/dry-configurable/compare/v0.12.0...v0.12.1)
|
66
|
+
|
67
|
+
## 0.12.0 2020-12-26
|
68
|
+
|
69
|
+
|
70
|
+
### Fixed
|
71
|
+
|
72
|
+
- Setting values provided by defaults and/or pre-processor blocks are no longer accidentally memoized across instances of classes including Dry::Configurable (#99) (@timriley & @esparta)
|
73
|
+
|
74
|
+
### Changed
|
75
|
+
|
76
|
+
- Instance behavior is now prepended, so that if you have your own `initialize`, calling `super` is no longer required (see #98 for more details) (@zabolotnov87)
|
77
|
+
- Switched to equalizer from dry-core (@solnic)
|
78
|
+
|
79
|
+
[Compare v0.11.6...v0.12.0](https://github.com/dry-rb/dry-configurable/compare/v0.11.6...v0.12.0)
|
80
|
+
|
81
|
+
## 0.11.6 2020-06-22
|
2
82
|
|
3
83
|
|
4
84
|
### Changed
|
@@ -6,7 +86,7 @@
|
|
6
86
|
- A meaningful error is raised when the extension is included more than once (issue #89 fixed via #94) (@landongrindheim)
|
7
87
|
- Evaluate setting input immediately when input is provided. This allows for earlier feedback from constructors designed to raise errors on invalid input (#95) (@timriley)
|
8
88
|
|
9
|
-
[Compare v0.11.5...
|
89
|
+
[Compare v0.11.5...v0.11.6](https://github.com/dry-rb/dry-configurable/compare/v0.11.5...v0.11.6)
|
10
90
|
|
11
91
|
## 0.11.5 2020-03-23
|
12
92
|
|
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
|
@@ -7,22 +8,22 @@
|
|
7
8
|
# dry-configurable [][chat]
|
8
9
|
|
9
10
|
[][gem]
|
10
|
-
[][actions]
|
11
12
|
[][codacy]
|
12
13
|
[][codacy]
|
13
14
|
[][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.6.0`
|
26
|
+
* ~~jruby~~ `>= 9.3` (we are waiting for [2.6 support](https://github.com/jruby/jruby/issues/6161))
|
26
27
|
|
27
28
|
## License
|
28
29
|
|
data/dry-configurable.gemspec
CHANGED
@@ -1,36 +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/master/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.6.0"
|
29
30
|
|
30
31
|
# to update dependencies edit project.yml
|
31
32
|
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
32
|
-
spec.add_runtime_dependency "dry-core", "~> 0.
|
33
|
-
spec.add_runtime_dependency "dry-equalizer", "~> 0.2"
|
33
|
+
spec.add_runtime_dependency "dry-core", "~> 0.6"
|
34
34
|
|
35
35
|
spec.add_development_dependency "bundler"
|
36
36
|
spec.add_development_dependency "rake"
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "set"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require "dry/configurable/constants"
|
6
|
+
require "dry/configurable/dsl"
|
7
|
+
require "dry/configurable/methods"
|
8
|
+
require "dry/configurable/settings"
|
9
9
|
|
10
10
|
module Dry
|
11
11
|
module Configurable
|
@@ -18,25 +18,27 @@ module Dry
|
|
18
18
|
|
19
19
|
parent_settings = (respond_to?(:config) ? config._settings : _settings)
|
20
20
|
|
21
|
-
klass.instance_variable_set(
|
21
|
+
klass.instance_variable_set("@_settings", parent_settings)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Add a setting to the configuration
|
25
25
|
#
|
26
|
-
# @param [Mixed]
|
26
|
+
# @param [Mixed] name
|
27
27
|
# The accessor key for the configuration value
|
28
28
|
# @param [Mixed] default
|
29
|
-
#
|
30
|
-
#
|
29
|
+
# Default value for the setting
|
30
|
+
# @param [#call] constructor
|
31
|
+
# Transformation given value will go through
|
32
|
+
# @param [Boolean] reader
|
33
|
+
# Whether a reader accessor must be created
|
31
34
|
# @yield
|
32
|
-
#
|
33
|
-
# a new configuration class, and bound as the default value
|
35
|
+
# A block can be given to add nested settings.
|
34
36
|
#
|
35
37
|
# @return [Dry::Configurable::Config]
|
36
38
|
#
|
37
39
|
# @api public
|
38
|
-
def setting(*args, &block)
|
39
|
-
setting = __config_dsl__.setting(*args, &block)
|
40
|
+
def setting(*args, **options, &block)
|
41
|
+
setting = __config_dsl__.setting(*args, **options, &block)
|
40
42
|
|
41
43
|
_settings << setting
|
42
44
|
|
@@ -74,7 +76,7 @@ module Dry
|
|
74
76
|
|
75
77
|
# @api private
|
76
78
|
def __config_dsl__
|
77
|
-
@
|
79
|
+
@__config_dsl__ ||= DSL.new
|
78
80
|
end
|
79
81
|
|
80
82
|
# @api private
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "dry/configurable/setting"
|
4
|
+
require "dry/configurable/settings"
|
5
5
|
|
6
6
|
module Dry
|
7
7
|
module Configurable
|
@@ -23,16 +23,10 @@ module Dry
|
|
23
23
|
public_send(:"visit_#{type}", rest)
|
24
24
|
end
|
25
25
|
|
26
|
-
# @api private
|
27
|
-
def visit_constructor(node)
|
28
|
-
setting, constructor = node
|
29
|
-
visit(setting).with(constructor: constructor)
|
30
|
-
end
|
31
|
-
|
32
26
|
# @api private
|
33
27
|
def visit_setting(node)
|
34
|
-
name,
|
35
|
-
Setting.new(name, **opts
|
28
|
+
name, opts = node
|
29
|
+
Setting.new(name, **opts)
|
36
30
|
end
|
37
31
|
|
38
32
|
# @api private
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "concurrent/map"
|
4
4
|
|
5
|
-
require
|
5
|
+
require "dry/core/equalizer"
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
7
|
+
require "dry/configurable/constants"
|
8
|
+
require "dry/configurable/errors"
|
9
9
|
|
10
10
|
module Dry
|
11
11
|
module Configurable
|
@@ -79,7 +79,6 @@ module Dry
|
|
79
79
|
.to_h
|
80
80
|
end
|
81
81
|
alias_method :to_h, :values
|
82
|
-
alias_method :to_hash, :values
|
83
82
|
|
84
83
|
# @api private
|
85
84
|
def finalize!
|
@@ -106,7 +105,7 @@ module Dry
|
|
106
105
|
super unless setting
|
107
106
|
|
108
107
|
if setting.writer?(meth)
|
109
|
-
raise FrozenConfig,
|
108
|
+
raise FrozenConfig, "Cannot modify frozen config" if frozen?
|
110
109
|
|
111
110
|
_settings << setting.with(input: args[0])
|
112
111
|
else
|
@@ -116,7 +115,7 @@ module Dry
|
|
116
115
|
|
117
116
|
# @api private
|
118
117
|
def resolve(meth)
|
119
|
-
_resolved.fetch(meth) { _resolved[meth] = meth.to_s.tr(
|
118
|
+
_resolved.fetch(meth) { _resolved[meth] = meth.to_s.tr("=", "").to_sym }
|
120
119
|
end
|
121
120
|
|
122
121
|
# @api private
|
data/lib/dry/configurable/dsl.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require "dry/configurable/constants"
|
4
|
+
require "dry/configurable/flags"
|
5
|
+
require "dry/configurable/setting"
|
6
|
+
require "dry/configurable/settings"
|
7
|
+
require "dry/configurable/compiler"
|
8
|
+
require "dry/core/deprecations"
|
8
9
|
|
9
10
|
module Dry
|
10
11
|
module Configurable
|
@@ -27,36 +28,137 @@ module Dry
|
|
27
28
|
instance_exec(&block) if block
|
28
29
|
end
|
29
30
|
|
30
|
-
#
|
31
|
+
# Registers a new setting node and compile it into a setting object
|
31
32
|
#
|
32
33
|
# @see ClassMethods.setting
|
33
|
-
# @api
|
34
|
+
# @api private
|
34
35
|
# @return Setting
|
35
|
-
def setting(name,
|
36
|
+
def setting(name, default = Undefined, **options, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
36
37
|
unless VALID_NAME.match?(name.to_s)
|
37
38
|
raise ArgumentError, "#{name} is not a valid setting name"
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
+
if default != Undefined
|
42
|
+
if Dry::Configurable.warn_on_setting_positional_default
|
43
|
+
Dry::Core::Deprecations.announce(
|
44
|
+
"default value as positional argument to settings",
|
45
|
+
"Provide a `default:` keyword argument instead",
|
46
|
+
tag: "dry-configurable",
|
47
|
+
uplevel: 2
|
48
|
+
)
|
49
|
+
end
|
41
50
|
|
42
|
-
|
51
|
+
options = options.merge(default: default)
|
52
|
+
end
|
43
53
|
|
44
|
-
|
54
|
+
if RUBY_VERSION < "3.0" &&
|
55
|
+
default == Undefined &&
|
56
|
+
(valid_opts, invalid_opts = valid_and_invalid_options(options)) &&
|
57
|
+
invalid_opts.any? &&
|
58
|
+
valid_opts.none?
|
59
|
+
# In Ruby 2.6 and 2.7, when a hash is given as the second positional argument
|
60
|
+
# (i.e. the hash is intended to be the setting's default value), and there are
|
61
|
+
# no other keyword arguments given, the hash is assigned to the `options`
|
62
|
+
# variable instead of `default`.
|
63
|
+
#
|
64
|
+
# For example, for this setting:
|
65
|
+
#
|
66
|
+
# setting :hash_setting, {my_hash: true}
|
67
|
+
#
|
68
|
+
# We'll have a `default` of `Undefined` and an `options` of `{my_hash: true}`
|
69
|
+
#
|
70
|
+
# If any additional keyword arguments are provided, e.g.:
|
71
|
+
#
|
72
|
+
# setting :hash_setting, {my_hash: true}, reader: true
|
73
|
+
#
|
74
|
+
# Then we'll have a `default` of `{my_hash: true}` and an `options` of `{reader:
|
75
|
+
# true}`, which is what we want.
|
76
|
+
#
|
77
|
+
# To work around that first case and ensure our (deprecated) backwards
|
78
|
+
# compatibility holds for Ruby 2.6 and 2.7, we extract all invalid options from
|
79
|
+
# `options`, and if there are no remaining valid options (i.e. if there were no
|
80
|
+
# keyword arguments given), then we can infer the invalid options to be a
|
81
|
+
# default hash value for the setting.
|
82
|
+
#
|
83
|
+
# This approach also preserves the behavior of raising an ArgumentError when a
|
84
|
+
# distinct hash is _not_ intentionally provided as the second positional
|
85
|
+
# argument (i.e. it's not enclosed in braces), and instead invalid keyword
|
86
|
+
# arguments are given alongside valid ones. So this setting:
|
87
|
+
#
|
88
|
+
# setting :some_setting, invalid_option: true, reader: true
|
89
|
+
#
|
90
|
+
# Would raise an ArgumentError as expected.
|
91
|
+
#
|
92
|
+
# However, the one case we can't catch here is when invalid options are supplied
|
93
|
+
# without hash literal braces, but there are no other keyword arguments
|
94
|
+
# supplied. In this case, a setting like:
|
95
|
+
#
|
96
|
+
# setting :hash_setting, my_hash: true
|
97
|
+
#
|
98
|
+
# Is parsed identically to the first case described above:
|
99
|
+
#
|
100
|
+
# setting :hash_setting, {my_hash: true}
|
101
|
+
#
|
102
|
+
# So in both of these cases, the default value will become `{my_hash: true}`. We
|
103
|
+
# consider this unlikely to be a problem in practice, since users are not likely
|
104
|
+
# to be providing invalid options to `setting` and expecting them to be ignored.
|
105
|
+
# Additionally, the deprecation messages will make the new behavior obvious, and
|
106
|
+
# encourage the users to upgrade their setting definitions.
|
45
107
|
|
46
|
-
|
108
|
+
if Dry::Configurable.warn_on_setting_positional_default
|
109
|
+
Dry::Core::Deprecations.announce(
|
110
|
+
"default value as positional argument to settings",
|
111
|
+
"Provide a `default:` keyword argument instead",
|
112
|
+
tag: "dry-configurable",
|
113
|
+
uplevel: 2
|
114
|
+
)
|
115
|
+
end
|
47
116
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
117
|
+
options = {default: invalid_opts}
|
118
|
+
end
|
119
|
+
|
120
|
+
if block && !block.arity.zero?
|
121
|
+
if Dry::Configurable.warn_on_setting_constructor_block
|
122
|
+
Dry::Core::Deprecations.announce(
|
123
|
+
"passing a constructor as a block",
|
124
|
+
"Provide a `constructor:` keyword argument instead",
|
125
|
+
tag: "dry-configurable",
|
126
|
+
uplevel: 2
|
127
|
+
)
|
53
128
|
end
|
129
|
+
|
130
|
+
options = options.merge(constructor: block)
|
131
|
+
block = nil
|
132
|
+
end
|
133
|
+
|
134
|
+
ensure_valid_options(options)
|
135
|
+
|
136
|
+
node = [:setting, [name.to_sym, options]]
|
137
|
+
|
138
|
+
if block
|
139
|
+
ast << [:nested, [node, DSL.new(&block).ast]]
|
54
140
|
else
|
55
141
|
ast << node
|
56
142
|
end
|
57
143
|
|
58
144
|
compiler.visit(ast.last)
|
59
145
|
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def ensure_valid_options(options)
|
150
|
+
return if options.none?
|
151
|
+
|
152
|
+
invalid_keys = options.keys - Setting::OPTIONS
|
153
|
+
|
154
|
+
raise ArgumentError, "Invalid options: #{invalid_keys.inspect}" unless invalid_keys.empty?
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns a tuple of valid and invalid options hashes derived from the options hash
|
158
|
+
# given to the setting
|
159
|
+
def valid_and_invalid_options(options)
|
160
|
+
options.partition { |k, _| Setting::OPTIONS.include?(k) }.map(&:to_h)
|
161
|
+
end
|
60
162
|
end
|
61
163
|
end
|
62
164
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/class_attributes"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Configurable
|
7
|
+
extend Core::ClassAttributes
|
8
|
+
|
9
|
+
# Set to false to suppress deprecation warning when a setting default is provided as a
|
10
|
+
# positional argument
|
11
|
+
defines :warn_on_setting_positional_default
|
12
|
+
warn_on_setting_positional_default true
|
13
|
+
|
14
|
+
# Set to false to suppress deprecation warning when a setting constructor is provided
|
15
|
+
# as a block
|
16
|
+
defines :warn_on_setting_constructor_block
|
17
|
+
warn_on_setting_constructor_block true
|
18
|
+
end
|
19
|
+
end
|
@@ -1,10 +1,23 @@
|
|
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
|
8
|
+
# Initializer method which is prepended when `Dry::Configurable`
|
9
|
+
# is included in a class
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
module Initializer
|
13
|
+
# @api private
|
14
|
+
def initialize(*)
|
15
|
+
@config = Config.new(self.class._settings.dup)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
19
|
+
end
|
20
|
+
|
8
21
|
# Instance-level API when `Dry::Configurable` is included in a class
|
9
22
|
#
|
10
23
|
# @api public
|
@@ -18,12 +31,6 @@ module Dry
|
|
18
31
|
# @api public
|
19
32
|
attr_reader :config
|
20
33
|
|
21
|
-
# @api private
|
22
|
-
def initialize(*)
|
23
|
-
@config = Config.new(self.class._settings.dup)
|
24
|
-
super
|
25
|
-
end
|
26
|
-
|
27
34
|
# Finalize the config and freeze the object
|
28
35
|
#
|
29
36
|
# @api public
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/configurable/errors"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Configurable
|
@@ -10,7 +10,7 @@ module Dry
|
|
10
10
|
module Methods
|
11
11
|
# @api public
|
12
12
|
def configure(&block)
|
13
|
-
raise FrozenConfig,
|
13
|
+
raise FrozenConfig, "Cannot modify frozen config" if frozen?
|
14
14
|
|
15
15
|
yield(config) if block
|
16
16
|
self
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "set"
|
4
4
|
|
5
|
-
require
|
5
|
+
require "dry/core/equalizer"
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
7
|
+
require "dry/configurable/constants"
|
8
|
+
require "dry/configurable/config"
|
9
9
|
|
10
10
|
module Dry
|
11
11
|
module Configurable
|
@@ -15,11 +15,11 @@ module Dry
|
|
15
15
|
class Setting
|
16
16
|
include Dry::Equalizer(:name, :value, :options, inspect: false)
|
17
17
|
|
18
|
-
OPTIONS = %i[input default reader constructor settings].freeze
|
18
|
+
OPTIONS = %i[input default reader constructor cloneable settings].freeze
|
19
19
|
|
20
20
|
DEFAULT_CONSTRUCTOR = -> v { v }.freeze
|
21
21
|
|
22
|
-
|
22
|
+
CLONEABLE_VALUE_TYPES = [Array, Hash, Set, Config].freeze
|
23
23
|
|
24
24
|
# @api private
|
25
25
|
attr_reader :name
|
@@ -53,11 +53,16 @@ module Dry
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
# @api private
|
57
|
+
def self.cloneable_value?(value)
|
58
|
+
CLONEABLE_VALUE_TYPES.any? { |type| value.is_a?(type) }
|
59
|
+
end
|
60
|
+
|
56
61
|
# @api private
|
57
62
|
def initialize(name, input: Undefined, default: Undefined, **options)
|
58
63
|
@name = name
|
59
64
|
@writer_name = :"#{name}="
|
60
|
-
@input = input
|
65
|
+
@input = input
|
61
66
|
@default = default
|
62
67
|
@options = options
|
63
68
|
|
@@ -110,8 +115,16 @@ module Dry
|
|
110
115
|
end
|
111
116
|
|
112
117
|
# @api private
|
113
|
-
def
|
114
|
-
|
118
|
+
def cloneable?
|
119
|
+
if options.key?(:cloneable)
|
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
|
115
128
|
end
|
116
129
|
|
117
130
|
private
|
@@ -119,13 +132,19 @@ module Dry
|
|
119
132
|
# @api private
|
120
133
|
def initialize_copy(source)
|
121
134
|
super
|
122
|
-
|
135
|
+
|
123
136
|
@options = source.options.dup
|
137
|
+
|
138
|
+
if source.cloneable?
|
139
|
+
@input = source.input.dup
|
140
|
+
@default = source.default.dup
|
141
|
+
@value = source.value.dup if source.evaluated?
|
142
|
+
end
|
124
143
|
end
|
125
144
|
|
126
145
|
# @api private
|
127
146
|
def evaluate
|
128
|
-
@value = constructor[
|
147
|
+
@value = constructor[Undefined.coalesce(input, default, nil)]
|
129
148
|
end
|
130
149
|
end
|
131
150
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "concurrent/map"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require "dry/core/equalizer"
|
6
|
+
require "dry/configurable/constants"
|
7
7
|
|
8
8
|
module Dry
|
9
9
|
module Configurable
|
data/lib/dry/configurable.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "concurrent/array"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
5
|
+
require "dry/configurable/constants"
|
6
|
+
require "dry/configurable/class_methods"
|
7
|
+
require "dry/configurable/instance_methods"
|
8
|
+
require "dry/configurable/config"
|
9
|
+
require "dry/configurable/setting"
|
10
|
+
require "dry/configurable/errors"
|
11
11
|
|
12
12
|
module Dry
|
13
13
|
# A simple configuration mixin
|
@@ -58,6 +58,7 @@ module Dry
|
|
58
58
|
klass.class_eval do
|
59
59
|
extend(ClassMethods)
|
60
60
|
include(InstanceMethods)
|
61
|
+
prepend(Initializer)
|
61
62
|
|
62
63
|
class << self
|
63
64
|
undef :config
|
data/lib/dry-configurable.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-configurable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
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: 2021-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -30,34 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
34
|
-
- - ">="
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 0.4.7
|
37
|
-
type: :runtime
|
38
|
-
prerelease: false
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - "~>"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '0.4'
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 0.4.7
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: dry-equalizer
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0.2'
|
33
|
+
version: '0.6'
|
54
34
|
type: :runtime
|
55
35
|
prerelease: false
|
56
36
|
version_requirements: !ruby/object:Gem::Requirement
|
57
37
|
requirements:
|
58
38
|
- - "~>"
|
59
39
|
- !ruby/object:Gem::Version
|
60
|
-
version: '0.
|
40
|
+
version: '0.6'
|
61
41
|
- !ruby/object:Gem::Dependency
|
62
42
|
name: bundler
|
63
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -118,8 +98,8 @@ files:
|
|
118
98
|
- lib/dry/configurable/config.rb
|
119
99
|
- lib/dry/configurable/constants.rb
|
120
100
|
- lib/dry/configurable/dsl.rb
|
121
|
-
- lib/dry/configurable/dsl/args.rb
|
122
101
|
- lib/dry/configurable/errors.rb
|
102
|
+
- lib/dry/configurable/flags.rb
|
123
103
|
- lib/dry/configurable/instance_methods.rb
|
124
104
|
- lib/dry/configurable/methods.rb
|
125
105
|
- lib/dry/configurable/setting.rb
|
@@ -142,14 +122,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
122
|
requirements:
|
143
123
|
- - ">="
|
144
124
|
- !ruby/object:Gem::Version
|
145
|
-
version: 2.
|
125
|
+
version: 2.6.0
|
146
126
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
127
|
requirements:
|
148
128
|
- - ">="
|
149
129
|
- !ruby/object:Gem::Version
|
150
130
|
version: '0'
|
151
131
|
requirements: []
|
152
|
-
rubygems_version: 3.
|
132
|
+
rubygems_version: 3.1.6
|
153
133
|
signing_key:
|
154
134
|
specification_version: 4
|
155
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
|