dry-configurable 0.8.0 → 0.11.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.
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/configurable/errors'
4
+
5
+ module Dry
6
+ module Configurable
7
+ # Common API for both classes and instances
8
+ #
9
+ # @api public
10
+ module Methods
11
+ # @api public
12
+ def configure(&block)
13
+ raise FrozenConfig, 'Cannot modify frozen config' if frozen?
14
+
15
+ yield(config) if block
16
+ self
17
+ end
18
+
19
+ # Finalize and freeze configuration
20
+ #
21
+ # @return [Dry::Configurable::Config]
22
+ #
23
+ # @api public
24
+ def finalize!
25
+ return self if config.frozen?
26
+
27
+ config.finalize!
28
+ self
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,36 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ require 'dry/equalizer'
6
+
7
+ require 'dry/configurable/constants'
8
+ require 'dry/configurable/config'
9
+
1
10
  module Dry
2
11
  module Configurable
3
12
  # This class represents a setting and is used internally.
4
13
  #
5
- # @private
14
+ # @api private
6
15
  class Setting
16
+ include Dry::Equalizer(:name, :value, :options)
17
+
18
+ OPTIONS = %i[input default reader constructor settings].freeze
19
+
20
+ DEFAULT_CONSTRUCTOR = -> v { v }.freeze
21
+
22
+ CLONABLE_VALUE_TYPES = [Array, Hash, Set, Config].freeze
23
+
24
+ # @api private
7
25
  attr_reader :name
8
26
 
27
+ # @api private
28
+ attr_reader :writer_name
29
+
30
+ # @api private
31
+ attr_reader :input
32
+
33
+ # @api private
34
+ attr_reader :default
35
+
36
+ # @api private
37
+ attr_reader :value
38
+
39
+ # @api private
9
40
  attr_reader :options
10
41
 
11
- attr_reader :processor
42
+ # Specialized Setting which includes nested settings
43
+ #
44
+ # @api private
45
+ class Nested < Setting
46
+ CONSTRUCTOR = Config.method(:new)
47
+
48
+ # @api private
49
+ def pristine
50
+ with(input: input.pristine)
51
+ end
12
52
 
13
- def initialize(name, value, processor, options = EMPTY_HASH)
14
- @name = name.to_sym
15
- @value = value
16
- @processor = processor
53
+ # @api private
54
+ def constructor
55
+ CONSTRUCTOR
56
+ end
57
+ end
58
+
59
+ # @api private
60
+ def initialize(name, input: Undefined, default: Undefined, **options)
61
+ @name = name
62
+ @writer_name = :"#{name}="
63
+ @input = input.equal?(Undefined) ? default : input
64
+ @default = default
17
65
  @options = options
66
+ set!
67
+ end
68
+
69
+ # @api private
70
+ def nested(settings)
71
+ Nested.new(name, input: settings, **options)
18
72
  end
19
73
 
20
- def value
21
- Undefined.default(@value, nil)
74
+ # @api private
75
+ def pristine
76
+ with(input: Undefined)
22
77
  end
23
78
 
24
- def undefined?
25
- Undefined.equal?(@value)
79
+ # @api private
80
+ def with(new_opts)
81
+ self.class.new(name, input: input, default: default, **options, **new_opts)
26
82
  end
27
83
 
84
+ # @api private
85
+ def constructor
86
+ options[:constructor] || DEFAULT_CONSTRUCTOR
87
+ end
88
+
89
+ # @api private
28
90
  def reader?
29
- options[:reader]
91
+ options[:reader].equal?(true)
92
+ end
93
+
94
+ # @api private
95
+ def writer?(meth)
96
+ writer_name.equal?(meth)
97
+ end
98
+
99
+ # @api private
100
+ def clonable_value?
101
+ CLONABLE_VALUE_TYPES.any? { |type| value.is_a?(type) }
102
+ end
103
+
104
+ private
105
+
106
+ # @api private
107
+ def initialize_copy(source)
108
+ super
109
+ @value = source.value.dup if source.clonable_value?
110
+ @options = source.options.dup
30
111
  end
31
112
 
32
- def node?
33
- Settings === @value
113
+ # @api private
114
+ def set!
115
+ @value = constructor[input.equal?(Undefined) ? nil : input]
34
116
  end
35
117
  end
36
118
  end
@@ -1,91 +1,71 @@
1
- require 'set'
2
- require 'concurrent/array'
3
- require 'dry/configurable/settings/argument_parser'
4
- require 'dry/configurable/setting'
5
- require 'dry/configurable/config'
1
+ # frozen_string_literal: true
2
+
3
+ require 'concurrent/map'
4
+
5
+ require 'dry/equalizer'
6
+ require 'dry/configurable/constants'
6
7
 
7
8
  module Dry
8
9
  module Configurable
9
- # A collection of settings. This is not part of the public API.
10
+ # A settings map
10
11
  #
11
- # @private
12
+ # @api private
12
13
  class Settings
13
- Parser = ArgumentParser.new.freeze
14
+ include Dry::Equalizer(:elements)
14
15
 
15
- class DSL
16
- def self.call(&block)
17
- new.instance_exec do
18
- instance_exec(&block)
19
- @settings
20
- end
21
- end
16
+ include Enumerable
22
17
 
23
- def initialize
24
- @settings = Settings.new
25
- end
18
+ # @api private
19
+ attr_reader :elements
26
20
 
27
- def setting(*args, &block)
28
- @settings.add(*args, &block)
29
- end
21
+ # @api private
22
+ def initialize(elements = EMPTY_ARRAY)
23
+ initialize_elements(elements)
30
24
  end
31
25
 
32
- # Capture nested config definition
33
- #
34
- # @return [Dry::Configurable::Setting]
35
- def self.capture(&block)
36
- DSL.(&block)
26
+ # @api private
27
+ def <<(setting)
28
+ elements[setting.name] = setting
29
+ self
37
30
  end
38
31
 
39
- attr_reader :settings
40
-
41
- attr_reader :config_class
42
-
43
- attr_reader :names
44
-
45
- def initialize(settings = ::Concurrent::Array.new)
46
- @settings = settings
47
- @config_class = Config[self]
48
- @names = Set.new(settings.map(&:name))
49
- yield(self) if block_given?
32
+ # @api private
33
+ def [](name)
34
+ elements[name]
50
35
  end
51
36
 
52
- def add(key, value = Undefined, options = Undefined, &block)
53
- extended = singleton_class < Configurable
54
- raise_already_defined_config(key) if extended && configured?
55
-
56
- Setting.new(key, *Parser.(value, options, block)).tap do |s|
57
- settings << s
58
- names << s.name
59
- end
60
- end
61
-
62
- def each
63
- settings.each { |s| yield(s) }
37
+ # @api private
38
+ def key?(name)
39
+ keys.include?(name)
64
40
  end
65
41
 
66
- def empty?
67
- settings.empty?
42
+ # @api private
43
+ def keys
44
+ elements.keys
68
45
  end
69
46
 
70
- def name?(name)
71
- names.include?(name)
47
+ # @api private
48
+ def each(&block)
49
+ elements.values.each(&block)
72
50
  end
73
51
 
74
- def dup
75
- Settings.new(settings.dup)
52
+ # @api private
53
+ def pristine
54
+ self.class.new(map(&:pristine))
76
55
  end
77
56
 
78
- def freeze
79
- settings.freeze
80
- super
81
- end
57
+ private
82
58
 
83
- def create_config
84
- config_class.new
59
+ # @api private
60
+ def initialize_copy(source)
61
+ initialize_elements(source.map(&:dup))
85
62
  end
86
63
 
87
- def config_defined?
88
- config_class.config_defined?
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
+ }
89
69
  end
90
70
  end
91
71
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  module Configurable
3
5
  # Methods meant to be used in a testing scenario
@@ -8,11 +10,7 @@ module Dry
8
10
  #
9
11
  # @api public
10
12
  def reset_config
11
- if self.is_a?(Class)
12
- @config = _settings.create_config
13
- else
14
- @config = self.class._settings.create_config
15
- end
13
+ @config = config.pristine
16
14
  end
17
15
  end
18
16
 
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  module Configurable
3
5
  # @api public
4
- VERSION = '0.8.0'.freeze
6
+ VERSION = '0.11.0'
5
7
  end
6
8
  end
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.8.0
4
+ version: 0.11.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: 2019-02-05 00:00:00.000000000 Z
11
+ date: 2020-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
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'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.2'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: bundler
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -86,38 +100,40 @@ dependencies:
86
100
  - - ">="
87
101
  - !ruby/object:Gem::Version
88
102
  version: '0'
89
- description:
103
+ description: A mixin to add configuration functionality to your classes
90
104
  email:
91
105
  - andyholland1991@aol.com
92
106
  executables: []
93
107
  extensions: []
94
108
  extra_rdoc_files: []
95
109
  files:
96
- - ".codeclimate.yml"
97
- - ".gitignore"
98
- - ".rspec"
99
- - ".travis.yml"
100
110
  - CHANGELOG.md
101
- - CONTRIBUTING.md
102
- - Gemfile
103
111
  - LICENSE
104
112
  - README.md
105
- - Rakefile
106
113
  - dry-configurable.gemspec
107
114
  - lib/dry-configurable.rb
108
115
  - lib/dry/configurable.rb
116
+ - lib/dry/configurable/class_methods.rb
117
+ - lib/dry/configurable/compiler.rb
109
118
  - lib/dry/configurable/config.rb
110
- - lib/dry/configurable/error.rb
119
+ - lib/dry/configurable/constants.rb
120
+ - lib/dry/configurable/dsl.rb
121
+ - lib/dry/configurable/dsl/args.rb
122
+ - lib/dry/configurable/errors.rb
123
+ - lib/dry/configurable/instance_methods.rb
124
+ - lib/dry/configurable/methods.rb
111
125
  - lib/dry/configurable/setting.rb
112
126
  - lib/dry/configurable/settings.rb
113
- - lib/dry/configurable/settings/argument_parser.rb
114
127
  - lib/dry/configurable/test_interface.rb
115
128
  - lib/dry/configurable/version.rb
116
- - rakelib/rubocop.rake
117
- homepage: https://github.com/dry-rb/dry-configurable
129
+ homepage: https://dry-rb.org/gems/dry-configurable
118
130
  licenses:
119
131
  - MIT
120
- metadata: {}
132
+ metadata:
133
+ allowed_push_host: https://rubygems.org
134
+ changelog_uri: https://github.com/dry-rb/dry-configurable/blob/master/CHANGELOG.md
135
+ source_code_uri: https://github.com/dry-rb/dry-configurable
136
+ bug_tracker_uri: https://github.com/dry-rb/dry-configurable/issues
121
137
  post_install_message:
122
138
  rdoc_options: []
123
139
  require_paths:
@@ -126,14 +142,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
142
  requirements:
127
143
  - - ">="
128
144
  - !ruby/object:Gem::Version
129
- version: 2.3.0
145
+ version: 2.4.0
130
146
  required_rubygems_version: !ruby/object:Gem::Requirement
131
147
  requirements:
132
148
  - - ">="
133
149
  - !ruby/object:Gem::Version
134
150
  version: '0'
135
151
  requirements: []
136
- rubygems_version: 3.0.1
152
+ rubygems_version: 3.0.3
137
153
  signing_key:
138
154
  specification_version: 4
139
155
  summary: A mixin to add configuration functionality to your classes
data/.codeclimate.yml DELETED
@@ -1,23 +0,0 @@
1
- engines:
2
- rubocop:
3
- enabled: true
4
- checks:
5
- Rubocop/Metrics/LineLength:
6
- enabled: true
7
- max: 120
8
- Rubocop/Style/Documentation:
9
- enabled: false
10
- Rubocop/Lint/HandleExceptions:
11
- enabled: true
12
- exclude:
13
- - rakelib/*.rake
14
- Rubocop/Style/FileName:
15
- enabled: true
16
- exclude:
17
- - lib/dry-configurable.rb
18
- ratings:
19
- paths:
20
- - lib/**/*.rb
21
- exclude_paths:
22
- - spec/**/*
23
- - examples/**/*