dry-initializer 3.0.2

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.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +12 -0
  3. data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +10 -0
  4. data/.github/ISSUE_TEMPLATE/---bug-report.md +34 -0
  5. data/.github/ISSUE_TEMPLATE/---feature-request.md +18 -0
  6. data/.github/workflows/custom_ci.yml +74 -0
  7. data/.github/workflows/docsite.yml +34 -0
  8. data/.github/workflows/sync_configs.yml +34 -0
  9. data/.gitignore +12 -0
  10. data/.rspec +4 -0
  11. data/.rubocop.yml +89 -0
  12. data/CHANGELOG.md +890 -0
  13. data/CODE_OF_CONDUCT.md +13 -0
  14. data/CONTRIBUTING.md +29 -0
  15. data/Gemfile +38 -0
  16. data/Guardfile +5 -0
  17. data/LICENSE +20 -0
  18. data/LICENSE.txt +21 -0
  19. data/README.md +89 -0
  20. data/Rakefile +8 -0
  21. data/benchmarks/compare_several_defaults.rb +82 -0
  22. data/benchmarks/plain_options.rb +63 -0
  23. data/benchmarks/plain_params.rb +84 -0
  24. data/benchmarks/with_coercion.rb +71 -0
  25. data/benchmarks/with_defaults.rb +66 -0
  26. data/benchmarks/with_defaults_and_coercion.rb +59 -0
  27. data/docsite/source/attributes.html.md +106 -0
  28. data/docsite/source/container-version.html.md +39 -0
  29. data/docsite/source/index.html.md +43 -0
  30. data/docsite/source/inheritance.html.md +43 -0
  31. data/docsite/source/optionals-and-defaults.html.md +130 -0
  32. data/docsite/source/options-tolerance.html.md +27 -0
  33. data/docsite/source/params-and-options.html.md +74 -0
  34. data/docsite/source/rails-support.html.md +101 -0
  35. data/docsite/source/readers.html.md +43 -0
  36. data/docsite/source/skip-undefined.html.md +59 -0
  37. data/docsite/source/type-constraints.html.md +160 -0
  38. data/dry-initializer.gemspec +20 -0
  39. data/lib/dry-initializer.rb +1 -0
  40. data/lib/dry/initializer.rb +61 -0
  41. data/lib/dry/initializer/builders.rb +7 -0
  42. data/lib/dry/initializer/builders/attribute.rb +81 -0
  43. data/lib/dry/initializer/builders/initializer.rb +61 -0
  44. data/lib/dry/initializer/builders/reader.rb +50 -0
  45. data/lib/dry/initializer/builders/signature.rb +32 -0
  46. data/lib/dry/initializer/config.rb +184 -0
  47. data/lib/dry/initializer/definition.rb +65 -0
  48. data/lib/dry/initializer/dispatchers.rb +112 -0
  49. data/lib/dry/initializer/dispatchers/build_nested_type.rb +59 -0
  50. data/lib/dry/initializer/dispatchers/check_type.rb +43 -0
  51. data/lib/dry/initializer/dispatchers/prepare_default.rb +40 -0
  52. data/lib/dry/initializer/dispatchers/prepare_ivar.rb +12 -0
  53. data/lib/dry/initializer/dispatchers/prepare_optional.rb +13 -0
  54. data/lib/dry/initializer/dispatchers/prepare_reader.rb +30 -0
  55. data/lib/dry/initializer/dispatchers/prepare_source.rb +28 -0
  56. data/lib/dry/initializer/dispatchers/prepare_target.rb +44 -0
  57. data/lib/dry/initializer/dispatchers/unwrap_type.rb +22 -0
  58. data/lib/dry/initializer/dispatchers/wrap_type.rb +27 -0
  59. data/lib/dry/initializer/dsl.rb +43 -0
  60. data/lib/dry/initializer/mixin.rb +15 -0
  61. data/lib/dry/initializer/mixin/local.rb +19 -0
  62. data/lib/dry/initializer/mixin/root.rb +11 -0
  63. data/lib/dry/initializer/struct.rb +39 -0
  64. data/lib/dry/initializer/undefined.rb +2 -0
  65. data/lib/tasks/benchmark.rake +41 -0
  66. data/lib/tasks/profile.rake +78 -0
  67. data/spec/attributes_spec.rb +38 -0
  68. data/spec/coercion_of_nil_spec.rb +25 -0
  69. data/spec/custom_dispatchers_spec.rb +35 -0
  70. data/spec/custom_initializer_spec.rb +30 -0
  71. data/spec/default_values_spec.rb +83 -0
  72. data/spec/definition_spec.rb +111 -0
  73. data/spec/invalid_default_spec.rb +13 -0
  74. data/spec/list_type_spec.rb +32 -0
  75. data/spec/missed_default_spec.rb +14 -0
  76. data/spec/nested_type_spec.rb +48 -0
  77. data/spec/optional_spec.rb +71 -0
  78. data/spec/options_tolerance_spec.rb +11 -0
  79. data/spec/public_attributes_utility_spec.rb +22 -0
  80. data/spec/reader_spec.rb +87 -0
  81. data/spec/repetitive_definitions_spec.rb +69 -0
  82. data/spec/several_assignments_spec.rb +41 -0
  83. data/spec/spec_helper.rb +29 -0
  84. data/spec/subclassing_spec.rb +49 -0
  85. data/spec/type_argument_spec.rb +35 -0
  86. data/spec/type_constraint_spec.rb +78 -0
  87. data/spec/value_coercion_via_dry_types_spec.rb +29 -0
  88. metadata +209 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f5d079daa17830b65177c99533e1b7f280bb4aee14dbcba097ba8c40de273abd
4
+ data.tar.gz: a59b00abe9c741b764152a6213ff40c29adbdf27094ecebbaaf766b2e056aa99
5
+ SHA512:
6
+ metadata.gz: 4fee1158d5ddd7bfca050f61788ee7012bf0a0f424239095ea649c6dd34ba47b157627efe7261f9e5fdaef405654b589addd26990a912b72cd0f76e339003754
7
+ data.tar.gz: 64a5e73606be0a238d0dba9173d32f90d8366d0aae64edf378dd851705a07d4ede0906ed241cc85ff9cb9b5c5f3fe9734bfb77d53fb6fc71bf29565b8607c388
@@ -0,0 +1,12 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ version: "2"
4
+
5
+ exclude_patterns:
6
+ - "benchmarks/"
7
+ - "examples/"
8
+ - "spec/"
9
+
10
+ plugins:
11
+ rubocop:
12
+ enabled: true
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: "⚠️ Please don't ask for support via issues"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: "\U0001F41B Bug report"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Before you submit this: WE ONLY ACCEPT BUG REPORTS AND FEATURE REQUESTS**
11
+
12
+ For more information see [our contribution guidelines](https://github.com/rom-rb/rom/blob/master/CONTRIBUTING.md)
13
+
14
+ **Before you report**
15
+
16
+ :warning: If you have a problem related to a schema, please **report it under [dry-schema issues](https://github.com/dry-rb/dry-schema/issues/new?assignees=&labels=bug&template=---bug-report.md&title=)** instead.
17
+
18
+ **Describe the bug**
19
+
20
+ A clear and concise description of what the bug is.
21
+
22
+ **To Reproduce**
23
+
24
+ Provide detailed steps to reproduce, an executable script would be best.
25
+
26
+ **Expected behavior**
27
+
28
+ A clear and concise description of what you expected to happen.
29
+
30
+ **Your environment**
31
+
32
+ - Affects my production application: **YES/NO**
33
+ - Ruby version: ...
34
+ - OS: ...
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: "\U0001F6E0 Feature request"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: feature
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ Summary of what the feature is supposed to do.
11
+
12
+ ## Examples
13
+
14
+ Code examples showing how the feature could be used.
15
+
16
+ ## Resources
17
+
18
+ Additional information, like a link to the discussion forum thread where the feature was discussed etc.
@@ -0,0 +1,74 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - .github/workflows/custom_ci.yml
7
+ - lib/**
8
+ - spec/**
9
+ - Gemfile
10
+ - "*.gemspec"
11
+
12
+ jobs:
13
+ tests-mri:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ ruby: ["2.6.x", "2.5.x", "2.4.x", "2.3.x"]
19
+ include:
20
+ - ruby: "2.6.x"
21
+ coverage: "true"
22
+ steps:
23
+ - uses: actions/checkout@v1
24
+ - name: Set up Ruby
25
+ uses: actions/setup-ruby@v1
26
+ with:
27
+ ruby-version: ${{matrix.ruby}}
28
+ - name: Download test reporter
29
+ if: "matrix.coverage == 'true'"
30
+ run: |
31
+ mkdir -p tmp/
32
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./tmp/cc-test-reporter
33
+ chmod +x ./tmp/cc-test-reporter
34
+ ./tmp/cc-test-reporter before-build
35
+ - name: Run all tests
36
+ env:
37
+ CI: "true"
38
+ COVERAGE: ${{matrix.coverage}}
39
+ run: |
40
+ gem install bundler
41
+ bundle config set without 'tools docs benchmarks'
42
+ bundle install --jobs 4 --retry 3
43
+ bundle exec rake
44
+ - name: Send coverage results
45
+ if: "matrix.coverage == 'true'"
46
+ env:
47
+ CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
48
+ GIT_COMMIT_SHA: ${{github.sha}}
49
+ GIT_BRANCH: ${{github.ref}}
50
+ GIT_COMMITTED_AT: ${{github.event.head_commit.timestamp}}
51
+ run: |
52
+ GIT_BRANCH=`ruby -e "puts ENV['GITHUB_REF'].split('/', 3).last"` \
53
+ GIT_COMMITTED_AT=`ruby -r time -e "puts Time.iso8601(ENV['GIT_COMMITTED_AT']).to_i"` \
54
+ ./tmp/cc-test-reporter after-build
55
+
56
+ tests-others:
57
+ runs-on: ubuntu-latest
58
+ strategy:
59
+ fail-fast: false
60
+ matrix:
61
+ image: ["jruby:9.2.8", "ruby:rc"]
62
+ container:
63
+ image: ${{matrix.image}}
64
+ steps:
65
+ - uses: actions/checkout@v1
66
+ - name: Install git
67
+ run: |
68
+ apt-get update
69
+ apt-get install -y --no-install-recommends git
70
+ - name: Run all tests
71
+ run: |
72
+ gem install bundler
73
+ bundle install --jobs 4 --retry 3 --without tools docs benchmarks
74
+ bundle exec rspec
@@ -0,0 +1,34 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ name: docsite
4
+
5
+ on:
6
+ push:
7
+ paths:
8
+ - docsite/**
9
+ - .github/workflows/docsite.yml
10
+ branches:
11
+ - master
12
+ - release-**
13
+ tags:
14
+
15
+ jobs:
16
+ update-docs:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v1
20
+ - name: Set up Ruby
21
+ uses: actions/setup-ruby@v1
22
+ with:
23
+ ruby-version: "2.6.x"
24
+ - name: Install dependencies
25
+ run: |
26
+ gem install bundler
27
+ bundle install --jobs 4 --retry 3 --without benchmarks sql
28
+ - name: Symlink ossy
29
+ run: mkdir -p bin && ln -sf "$(bundle show ossy)/bin/ossy" bin/ossy
30
+ - name: Trigger dry-rb.org deploy
31
+ env:
32
+ GITHUB_LOGIN: dry-bot
33
+ GITHUB_TOKEN: ${{ secrets.GH_PAT }}
34
+ run: bin/ossy github workflow dry-rb/dry-rb.org ci
@@ -0,0 +1,34 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ name: sync_configs
4
+
5
+ on:
6
+ repository_dispatch:
7
+
8
+ jobs:
9
+ sync-configs:
10
+ runs-on: ubuntu-latest
11
+ if: github.event.action == 'sync_configs'
12
+ steps:
13
+ - uses: actions/checkout@v1
14
+ - name: Update configuration files from devtools
15
+ env:
16
+ GITHUB_LOGIN: dry-bot
17
+ GITHUB_TOKEN: ${{ secrets.GH_PAT }}
18
+ run: |
19
+ git clone https://github.com/dry-rb/devtools.git tmp/devtools
20
+
21
+ if [ -f ".github/workflows/custom_ci.yml" ]; then
22
+ rsync -av --exclude '.github/workflows/ci.yml' tmp/devtools/shared/ . ;
23
+ else
24
+ rsync -av tmp/devtools/shared/ . ;
25
+ fi
26
+
27
+ git config --local user.email "dry-bot@dry-rb.org"
28
+ git config --local user.name "dry-bot"
29
+ git add -A
30
+ git commit -m "[devtools] config sync" || echo "nothing changed"
31
+ - name: Push changes
32
+ uses: ad-m/github-push-action@master
33
+ with:
34
+ github_token: ${{ secrets.GH_PAT }}
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /*.gem
11
+
12
+ .vscode
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --require spec_helper
3
+ --order random
4
+
@@ -0,0 +1,89 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.4
5
+
6
+ Style/EachWithObject:
7
+ Enabled: false
8
+
9
+ Style/StringLiterals:
10
+ Enabled: true
11
+ EnforcedStyle: single_quotes
12
+
13
+ Style/Alias:
14
+ Enabled: false
15
+
16
+ Style/LambdaCall:
17
+ Enabled: false
18
+
19
+ Style/StabbyLambdaParentheses:
20
+ Enabled: false
21
+
22
+ Style/FormatString:
23
+ Enabled: false
24
+
25
+ Style/Documentation:
26
+ Enabled: false
27
+
28
+ Layout/SpaceInLambdaLiteral:
29
+ Enabled: false
30
+
31
+ Layout/MultilineMethodCallIndentation:
32
+ Enabled: true
33
+ EnforcedStyle: indented
34
+
35
+ Metrics/LineLength:
36
+ Max: 100
37
+
38
+ Metrics/MethodLength:
39
+ Max: 22
40
+
41
+ Metrics/ClassLength:
42
+ Max: 150
43
+
44
+ Metrics/AbcSize:
45
+ Max: 20
46
+
47
+ Metrics/BlockLength:
48
+ Enabled: false
49
+
50
+ Metrics/CyclomaticComplexity:
51
+ Enabled: true
52
+ Max: 10
53
+
54
+ Lint/BooleanSymbol:
55
+ Enabled: false
56
+
57
+ Style/AccessModifierDeclarations:
58
+ Enabled: false
59
+
60
+ Style/BlockDelimiters:
61
+ Enabled: false
62
+
63
+ Layout/IndentFirstArrayElement:
64
+ EnforcedStyle: consistent
65
+
66
+ Style/ClassAndModuleChildren:
67
+ Exclude:
68
+ - "spec/**/*_spec.rb"
69
+
70
+ Lint/HandleExceptions:
71
+ Exclude:
72
+ - "spec/spec_helper.rb"
73
+
74
+ Naming/FileName:
75
+ Exclude:
76
+ - "lib/dry-*.rb"
77
+
78
+ Style/SymbolArray:
79
+ Exclude:
80
+ - "spec/**/*_spec.rb"
81
+
82
+ Style/ConditionalAssignment:
83
+ Enabled: false
84
+
85
+ Naming/MethodName:
86
+ Enabled: false
87
+
88
+ Style/AsciiComments:
89
+ Enabled: false
@@ -0,0 +1,890 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+ ## [3.0.2] [2019-11-07]
9
+
10
+ ### Fixed
11
+
12
+ - Warnings about keyword arguments (flash-gordon)
13
+
14
+ ## [3.0.1] [2019-04-15]
15
+
16
+ ### Fixed
17
+
18
+ - Usage of underscored names of `option`-s and `param`-s (nepalez)
19
+
20
+ You can use any sequence of underscores except for in nested types.
21
+ In nested types single underscores can be used to split alphanumeric
22
+ parts only.
23
+
24
+ ```ruby
25
+ class Test
26
+ extend Dry::Initializer
27
+
28
+ # Proper usage
29
+ option :foo_bar do
30
+ option :__foo__, proc(&:to_s)
31
+ end
32
+ end
33
+
34
+ # Improper usage
35
+ option :__foo__ do
36
+ # ...
37
+ end
38
+
39
+ option :foo__bar do
40
+ # ...
41
+ end
42
+ end
43
+ ```
44
+
45
+ This restriction is necessary because we constantize option/param names
46
+ when defining nested structs.
47
+
48
+ ## [3.0.0] [2019-04-14]
49
+
50
+ ### Added
51
+
52
+ - Support of wrapped types/coercers (nepalez)
53
+
54
+ ```ruby
55
+ class Test
56
+ # Wrap type to the array
57
+ param :foo, [proc(&:to_s)]
58
+ end
59
+
60
+ # And the value will be wrapped as well
61
+ test = Test.new(42)
62
+ test.foo # => ["42"]
63
+ ```
64
+
65
+ - It works with several layers of nesting (nepalez)
66
+
67
+ ```ruby
68
+ class Test
69
+ # Wrap type to the array
70
+ param :foo, [[proc(&:to_s)]]
71
+ end
72
+
73
+ # And the value will be wrapped as well
74
+ test = Test.new(42)
75
+ test.foo # => [["42"]]
76
+ ```
77
+
78
+ - Support of nested types/coercers (nepalez)
79
+
80
+ ```ruby
81
+ class Test
82
+ param :foo do
83
+ option :bar do
84
+ option :baz, proc(&:to_s)
85
+ end
86
+ end
87
+ end
88
+
89
+ test = Test.new(bar: { "baz" => 42 })
90
+ test.foo.bar.baz # => "42"
91
+ ```
92
+
93
+ - Wrapped/nested combinations are supported as well (nepalez)
94
+
95
+ ```ruby
96
+ class Test
97
+ param :foo, [] do
98
+ option :bar, proc(&:to_s)
99
+ end
100
+ end
101
+
102
+ test = Test.new(bar: 42)
103
+ test.foo.first.bar # => "42"
104
+ ```
105
+
106
+ ## [2.7.0] Unreleazed
107
+
108
+ ### Fixed
109
+
110
+ - Roll back master to the state of [2.5.0].
111
+
112
+ Somehow distinction between `@default_null` and `@null` variables
113
+ in the `Dry::Initializer::Builders` broken the `rom` library.
114
+
115
+ The version [2.6.0] has been yanked on rubygems, so the master
116
+ was rolled back to the previous state until the reason for
117
+ the incompatibility become clear (bjeanes, nepalez)
118
+
119
+ ## [2.6.0] [2018-09-09] (YANKED)
120
+
121
+ ## [2.5.0] [2018-08-17]
122
+
123
+ ### Fixed
124
+
125
+ - `nil` coercion (belousovAV)
126
+
127
+ When default value is `nil` instead of `Dry::Initializer::UNDEFINED`,
128
+ the coercion should be applied to any value, including `nil`, because
129
+ we cannot distinct "undefined" `nil` from the "assigned" `nil` value.
130
+
131
+ ## [2.4.0] [2018-02-01]
132
+
133
+ ### Added
134
+ - Dispatchers for adding syntax sugar to `param` and `options` (nepalez)
135
+
136
+ ```ruby
137
+ # Converts `integer: true` to `type: proc(&:to_i)`
138
+ dispatcher = ->(op) { op[:integer] ? op.merge(type: proc(&:to_i)) : op }
139
+ # Register a dispatcher
140
+ Dry::Initializer::Dispatchers << dispatcher
141
+ # Use syntax sugar
142
+ class User
143
+ param :id, integer: true # same as param :id, proc(&:to_i)
144
+ end
145
+ ```
146
+
147
+ ## [2.3.0] [2017-09-19]
148
+
149
+ ### Added
150
+ - Type coercer can take second argument for the initialized instance (nepalez)
151
+ This allows to wrap assigned value to the object that refers back
152
+ to the initializer instance. More verbose example:
153
+
154
+ ```ruby
155
+ class Location < String
156
+ attr_reader :parameter # refers back to its parameter
157
+
158
+ def initialize(name, parameter)
159
+ super(name)
160
+ @parameter = parameter
161
+ end
162
+ end
163
+
164
+ class Parameter
165
+ extend Dry::Initializer
166
+ param :name
167
+ param :location, ->(value, param) { Location.new(value, param) }
168
+ end
169
+
170
+ offset = Parameter.new "offset", location: "query"
171
+ offset.name # => "offset"
172
+ offset.location # => "query"
173
+ offset.location.parameter == offset # true
174
+ ```
175
+
176
+ ## [2.2.0] [2017-09-13]
177
+
178
+ ### Added
179
+ - Option `:desc` for option/param to add a description (nepalez)
180
+
181
+ - Methods `Definition#inch` and `Config#inch` to inspect definitions (nepalez)
182
+
183
+ ```ruby
184
+ class User
185
+ extend Dry::Initializer
186
+ option :name, proc(&:to_s), optional: true, desc: "User name"
187
+ option :email, optional: true, desc: "user email"
188
+ end
189
+
190
+ User.dry_initializer.inch
191
+ # @!method initialize(*, **options)
192
+ # Initializes an instance of User
193
+ # @option [Object] :name (optional) User name
194
+ # @option [Object] :email (optional) User email
195
+ # @return [User]
196
+ ```
197
+
198
+ ## [2.1.0] [2017-09-11]
199
+
200
+ ### Added
201
+ - Method `#options` to param/option definition (nepalez)
202
+
203
+ ```ruby
204
+ class User
205
+ extend Dry::Initializer
206
+ option :name, proc(&:to_s), optional: true
207
+ option :email, optional: true
208
+ end
209
+
210
+ User.dry_initializer.options.map do |option|
211
+ [option.source, option.options]
212
+ end
213
+ # => [
214
+ # [:name, { type: proc(&:to_s), as: :name, optional: true }],
215
+ # [:email, { as: :email, optional: true }]
216
+ # ]
217
+ ```
218
+
219
+ This method can be helpful for replicating params/options
220
+ in another class without inheritance.
221
+
222
+ ## [2.0.0] [2017-08-28]
223
+
224
+ The gem has been rewritten under the hood keeping its documented
225
+ interface about the same (see "Deleted" section below for the only
226
+ backward-incompatible change).
227
+
228
+ The main achievement of this version is fixing an edge case where
229
+ change in params/options of superclass wasn't reflected in its
230
+ previously declared subclasses.
231
+
232
+ Thanks to @solnic for the idea of class-level container,
233
+ and to @gzigzigzeo for persuading me to do this refactoring.
234
+
235
+ ### Deleted
236
+ - Undocumented variable `@__option__` which was the main reason for refactoring
237
+ (gzigzigzeo, nepalez).
238
+
239
+ ### Added
240
+ - Class method `.dry_initializer` -- a container for `.params` and `.options`
241
+ `.definitions` along with the `.null` setting (either `nil` or `UNDEFINED`)
242
+ used for unassigned values (nepalez)
243
+
244
+ - `.dry_initializer.attributes` method takes an instance of the same class
245
+ and returns the hash of assigned options. This provide the same
246
+ functionality as previously used instance variable `@__options__` (nepalez)
247
+
248
+ ```ruby
249
+ object.class.dry_initializer.attributes(object)
250
+ ```
251
+
252
+ When you use "Dry::Initializer.define -> { ... }" syntax,
253
+ the class method `.dry_initializer` is not defined. To access attributes
254
+ you should use private instance method `#__dry_initializer_config__` instead:
255
+
256
+ ```ruby
257
+ object.send(:__dry_initializer_config__).attributes(object)
258
+ ```
259
+
260
+ Both methods `.dry_initializer` and `#__dry_initializer_config__` refer
261
+ to the same object.
262
+
263
+ - `.dry_initializer.public_attributes`. This method works differently:
264
+ it looks through (possibly reloaded) readers instead of variables
265
+ (gzigzigzeo, nepalez)
266
+
267
+ ```ruby
268
+ object.class.dry_initializer.public_attributes(object)
269
+ ```
270
+
271
+ You can use the same trick as above mutatis mutandis.
272
+
273
+ ### Fixed
274
+ - Definition order dependency bug (nepalez)
275
+
276
+ I've found out that if you provided a subclass and then changed params
277
+ or options of its superclass, these changes woudn't be reflected in
278
+ subclasses until you change any of it params/options as well.
279
+
280
+ Now this bug is fixed: every time you call `param` or `option` at
281
+ any class, the gem scans through all its descendants to the very bottom
282
+ of the tree, and reloads their defintitions.
283
+
284
+ Being done in load time, the rebuilt makes no effect on runtime performance.
285
+
286
+ - Possible misbehavior when you define param and option with the same name (nepalez)
287
+
288
+ Doing this will provide `option :name` only, not both:
289
+
290
+ ```ruby
291
+ param :name
292
+ option :name
293
+ ```
294
+
295
+ - Attempt to redefine param/option of superclass with option/param in
296
+ its subclass will cause an exception because it would break
297
+ Liskov substitute principle with unexpected behaviour (nepalez)
298
+
299
+ No, you can do neither these definitions, nor vice versa:
300
+
301
+ ```ruby
302
+ class Foo
303
+ extend Dry::Intitializer
304
+ param :name
305
+ end
306
+
307
+ class Bar < Foo
308
+ option :name
309
+ end
310
+ ```
311
+
312
+ - When you reloading previously defined param of superclass, the gem
313
+ will check all its descendands for whether all required positional params
314
+ goes before optional ones (nepalez)
315
+
316
+ ```ruby
317
+ class Foo
318
+ param :name
319
+ # Foo: def initializer(name)
320
+ end
321
+
322
+ class Bar
323
+ param :email
324
+ # Bar: def initializer(name, email)
325
+ end
326
+
327
+ class Foo
328
+ # This raises SyntaxError because in Bar this would cause wrong definition
329
+ # Foo: def initializer(name = nil)
330
+ # Bar: def initializer(name = nil, email)
331
+ param :name, optional: true
332
+ end
333
+ ```
334
+
335
+ ### Changed
336
+ - Under the hood I've separated param/option settings declaration (a container
337
+ with param/option settings) from code builders for initializer and readers
338
+ (nepalez)
339
+
340
+ You can check both the code for the `__initializer__`:
341
+
342
+ ```ruby
343
+ class Foo
344
+ extend Dry::Initializer
345
+ # ...
346
+ end
347
+
348
+ Foo.dry_initializer.code
349
+ ```
350
+
351
+ and readers:
352
+
353
+ ```ruby
354
+ Foo.dry_initializer.params.map(&:code)
355
+ Foo.dry_initializer.options.map(&:code)
356
+
357
+ # or
358
+
359
+ Foo.dry_initializer.definitions.values.map(&:code)
360
+ ```
361
+
362
+ You can also check settings for every param and option using methods
363
+ `dry_initializer.params`, `dry_initializer.options` (lists), or
364
+ `dry_initializer.definitions` (hash).
365
+
366
+ You can check null value via `.dry_initializer.null` which is different
367
+ for `Dry::Initializer` and `Dry::Initializer[undefined: false]` modules.
368
+
369
+ - Optimized the code for `__initializer__`-s (the method where all magics occurs)
370
+ (nepalez)
371
+
372
+ Benchmarks remained about the same:
373
+
374
+ ```shell
375
+ rake benchmark
376
+ ```
377
+
378
+ ```
379
+ Benchmark for instantiation with plain params
380
+ value_struct: 4317196.9 i/s
381
+ plain Ruby: 4129803.9 i/s - 1.05x slower
382
+ dry-initializer: 1710702.1 i/s - 2.52x slower
383
+ concord: 1372630.4 i/s - 3.15x slower
384
+ values: 601651.8 i/s - 7.18x slower
385
+ attr_extras: 535599.5 i/s - 8.06x slower
386
+ ```
387
+
388
+ ```
389
+ Benchmark for instantiation with plain options
390
+ plain Ruby: 1769174.1 i/s
391
+ dry-initializer: 636634.1 i/s - 2.78x slower
392
+ kwattr: 423296.5 i/s - 4.18x slower
393
+ anima: 399415.0 i/s - 4.43x slower
394
+ ```
395
+
396
+ ```
397
+ Benchmark for instantiation with coercion
398
+ plain Ruby: 1565501.0 i/s
399
+ fast_attributes: 569952.9 i/s - 2.75x slower
400
+ dry-initializer: 461122.1 i/s - 3.39x slower
401
+ virtus: 138074.8 i/s - 11.34x slower
402
+ ```
403
+
404
+ ```
405
+ Benchmark for instantiation with default values
406
+ plain Ruby: 3402455.4 i/s
407
+ kwattr: 586206.5 i/s - 5.80x slower
408
+ dry-initializer: 528482.2 i/s - 6.44x slower
409
+ active_attr: 298697.7 i/s - 11.39x slower
410
+ ```
411
+
412
+ ```
413
+ Benchmark for instantiation with type constraints and default values
414
+ plain Ruby: 2881696.1 i/s
415
+ dry-initializer: 470815.1 i/s - 6.12x slower
416
+ virtus: 180272.6 i/s - 15.99x slower
417
+ ```
418
+
419
+ ## [1.4.1] [2017-04-05]
420
+
421
+ ### Fixed
422
+ - Warning about redefined `#initialize` in case the method reloaded in a klass
423
+ that extends the module (nepalez, sergey-chechaev)
424
+
425
+ ### Changed
426
+ - Rename `Dry::Initializer::DSL` -> `Dry::Initializer::ClassDSL` (nepalez)
427
+ - Add `Dry::Initializer::InstanceDSL` (nepalez)
428
+
429
+ ### Deprecated
430
+ - `Dry::Initializer::Mixin`. In latest version this was an alias for
431
+ `Dry::Initializer` that kept for backward compatibility for early versions of the gem.
432
+
433
+ This story will come to the end in `v2.1.0`.
434
+
435
+ ## [1.4.0] [2017-03-08]
436
+
437
+ ### Changed (backward-incompatible)
438
+ - The `@__options__` hash now collects all assigned attributes,
439
+ collected via `#option` (as before), and `#param` (nepalez)
440
+
441
+ ## [1.3.0] [2017-03-05]
442
+
443
+ ### Added
444
+ - No-undefined configuration of the initializer (nepalez, flash-gordon)
445
+
446
+ You can either extend or include module `Dry::Initializer` with additional option
447
+ `[undefined: false]`. This time `nil` will be assigned instead of
448
+ `Dry::Initializer::UNDEFINED`. Readers becomes faster because there is no need
449
+ to chech whether a variable was defined or not. At the same time the initializer
450
+ doesn't distinct cases when a variable was set to `nil` explicitly, and when it wasn's set at all:
451
+
452
+ class Foo # old behavior
453
+ extend Dry::Initializer
454
+ param :qux, optional: true
455
+ end
456
+
457
+ class Bar # new behavior
458
+ extend Dry::Initializer[undefined: false]
459
+ param :qux, optional: true
460
+ end
461
+
462
+ Foo.new.instance_variable_get(:@qux) # => Dry::Initializer::UNDEFINED
463
+ Bar.new.instance_variable_get(:@qux) # => nil
464
+
465
+ ### Changed
466
+ - Fixed method definitions for performance at the load time (nepalez, flash-gordon)
467
+
468
+ ## [1.2.0] [2017-03-05]
469
+
470
+ ### Fixed
471
+ - The `@__options__` variable collects renamed options after default values and coercions were applied (nepalez)
472
+
473
+ ## [1.1.3] [2017-03-01]
474
+
475
+ ### Added
476
+ - Support for lambdas as default values (nepalez, gzigzigzeo)
477
+
478
+ ## [1.1.2] [2017-02-06]
479
+
480
+ ### Changed
481
+ - Remove previously defined methods before redefining them (flash-gordon)
482
+
483
+ ## [1.1.1] [2017-02-04]
484
+
485
+ ### Fixed
486
+ - `@__options__` collects defined options only (nepalez)
487
+
488
+ ## [1.1.0] [2017-01-28]
489
+
490
+ ### Added
491
+ - enhancement via `Dry::Initializer::Attribute.dispatchers` registry (nepalez)
492
+
493
+ ```ruby
494
+ # Register dispatcher for `:string` option
495
+ Dry::Initializer::Attribute.dispatchers << ->(string: nil, **op) do
496
+ string ? op.merge(type: proc(&:to_s)) : op
497
+ end
498
+
499
+ # Now you can use the `:string` key for `param` and `option`
500
+ class User
501
+ extend Dry::Initializer
502
+ param :name, string: true
503
+ end
504
+
505
+ User.new(:Andy).name # => "Andy"
506
+ ```
507
+
508
+ ### Changed
509
+ - optimize assignments for performance (nepalez)
510
+
511
+ ## [1.0.0] [2017-01-22]
512
+
513
+ In this version the code has been rewritten for simplicity
514
+
515
+ ### Changed
516
+ - [BREAKING] when `param` or `option` was not defined, the corresponding **variable** is set to `Dry::Initializer::UNDEFINED`, but the **reader** (when defined) will return `nil` (nepalez)
517
+
518
+ - `Dry::Initializer` and `Dry::Initializer::Mixin` became aliases (nepalez)
519
+
520
+ ### Added
521
+ - support for reloading `param` and `option` definitions (nepalez)
522
+
523
+ class User
524
+ extend Dry::Initializer
525
+ param :name
526
+ param :phone, optional: true
527
+ end
528
+
529
+ User.new # => Boom!
530
+
531
+ class Admin < User
532
+ param :name, default: proc { 'Merlin' }
533
+ end
534
+
535
+ # order of the param not changed
536
+ Admin.new.name # => "Merlin"
537
+
538
+ - support for assignment of attributes via several options (nepalez)
539
+
540
+ class User
541
+ extend Dry::Initializer
542
+ option :phone
543
+ option :number, as: :phone
544
+ end
545
+
546
+ # Both ways provide the same result
547
+ User.new(phone: '1234567890').phone # => '1234567890'
548
+ User.new(number: '1234567890').phone # => '1234567890'
549
+
550
+ ## [0.11.0] [2017-01-02]
551
+
552
+ ### Added
553
+ - Support of reloading `#initializer` with `super` (nepalez)
554
+
555
+ ### Internal
556
+ - Refactor the way [#initializer] method is (re)defined (nepalez)
557
+
558
+ When you extend class with `Dry::Initializer::Mixin`, the initializer is
559
+ defined not "inside" the class per se, but inside the included module. The
560
+ reference to that module is stored as class-level `__initializer_mixin__`.
561
+
562
+ Mixin method [#initialize] calls another private method [#__initialize__].
563
+ It is this method to be reloaded every time you envoke a helper
564
+ `option` or `product`.
565
+
566
+ When new subclass is inherited, new mixin is added to chain of accessors,
567
+ but this time it does reload `__initialize__` only, not the `initialize`.
568
+ That is how you can safely reload initializer using `super`, but at the same
569
+ time use the whole power of dry-initializer DSL both in parent class and its
570
+ subclasses.
571
+
572
+ The whole stack of accessors looks like the following:
573
+ - Parent class mixin: `initialize` --> `__initialize__`
574
+ ^
575
+ - Parent class: `initialize`
576
+ - Subclass mixin: ^ `__initialize__`
577
+ - Subclass: `initialize`
578
+
579
+ See specification `spec/custom_initializer_spec.rb` to see how this works.
580
+
581
+ ## [0.10.2] [2016-12-31]
582
+
583
+ ### Added
584
+ - Support of Ruby 2.4 (flas-gordon)
585
+
586
+ ### Internal
587
+ - Code clearance for ROM integration (flash-gordon)
588
+
589
+ ## [0.10.1] [2016-12-27]
590
+
591
+ ### Fixed
592
+ - Wrong arity when there were no options and the last param had a default (nolith)
593
+
594
+ ## [0.10.0] [2016-11-20]
595
+
596
+ ### Deleted (BREAKING CHANGE!)
597
+ - Deprecated method DSL#using (nepalez)
598
+
599
+ ## [0.9.3] [2016-11-20]
600
+
601
+ ### Deprecated
602
+ - After discussion in [PR #17]: https://github.com/dry-rb/dry-initializer/pull/17)
603
+ (many thanks to @sahal2080 and @hrom512 for starting that issue and PR),
604
+ the method `using` is deprecated and will be removed from v0.10.0 (nepalez)
605
+
606
+ ### Fixed
607
+ - Support of weird option names (nepalez)
608
+
609
+ ```ruby
610
+ option :"First name", as: :first_name
611
+ ```
612
+
613
+ ## [0.9.2] [2016-11-10]
614
+
615
+ ### Fixed
616
+ - Validation of attributes (params and options) (nepalez)
617
+
618
+ ## [0.9.1] [2016-11-06]
619
+
620
+ ### Added
621
+ - Support for renaming an option during initialization (nepalez)
622
+
623
+ option :name, as: :username # to take :name option and create :username attribute
624
+
625
+ ## [0.9.0] [2016-11-06]
626
+
627
+ ### Added
628
+ - The method `#initialize` is defined when a class extended the module (nepalez)
629
+
630
+ In previous versions the method was defined only by `param` and `option` calls.
631
+
632
+ ### Breaking Changes
633
+ - The initializer accepts any option (but skips unknown) from the very beginning (nepalez)
634
+
635
+ ### Deleted
636
+ - Deprecated methods `tolerant_to_unknown_options` and `intolerant_to_unknown_options` (nepalez)
637
+
638
+ ### Internal
639
+ - Refactor scope (`using`) to support methods renaming and aliasing (nepalez)
640
+
641
+ ## [0.8.1] [2016-11-05]
642
+
643
+ ### Added
644
+ - Support for `dry-struct`ish syntax for constraints (type as a second parameter) (nepalez)
645
+
646
+ option :name, Dry::Types['strict.string']
647
+
648
+ ## [0.8.0] [2016-11-05]
649
+
650
+ In this version we switched from key arguments to ** to support special keys:
651
+
652
+ option :end
653
+ option :begin
654
+
655
+ In previous versions this was translated to
656
+
657
+ def initialize(end:, begin:)
658
+ @end = end # BOOM! SyntaxError!
659
+ @begin = begin # Potential BOOM (unreached)
660
+ end
661
+
662
+ Now the assignment is imlemented like this:
663
+
664
+ def initialize(**__options__)
665
+ @end = __options__.fetch(:end)
666
+ @begin = __options__.fetch(:begin)
667
+ end
668
+
669
+ As a side effect of the change the initializer becomes tolerant
670
+ to any unknown option if, and only if some `option` was set explicitly.
671
+
672
+ Methods `tolerant_to_unknown_options` and `intolerant_to_unknown_options`
673
+ are deprecated and will be removed in the next version of the gem.
674
+
675
+ ### Added
676
+ - support for special options like `option :end`, `option :begin` etc. (nepalez)
677
+
678
+ ### Changed
679
+ - switched from key arguments to serialized hash argument in the initializer (nepalez)
680
+
681
+ ### Breaking Changes
682
+ - the initializer becomes tolerant to unknown options when any `option` was set,
683
+ ignoring `intolerant_to_unknown_options` helper.
684
+
685
+ - the initializer becomes intolerant to options when no `option` was set,
686
+ ignoring `tolerant_to_unknown_options` helper.
687
+
688
+ ### Deprecated
689
+ - `tolerant_to_unknown_options`
690
+ - `intolerant_to_unknown_options`
691
+
692
+ ## [0.7.0] [2016-10-11]
693
+
694
+ ### Added
695
+ - Shared settings with `#using` method (nepalez)
696
+
697
+ ## [0.6.0] [2016-10-09]
698
+
699
+ ### Added
700
+ - Support for private and protected readers in the `reader:` option (jmgarnier)
701
+
702
+ ## [0.5.0] [2016-08-21]
703
+
704
+ ### Added
705
+ - Allow `optional` attribute to be left undefined (nepalez)
706
+
707
+ ## [0.4.0] [2016-05-28]
708
+
709
+ ### Deleted (backward-incompatible changes)
710
+ - Support of modules and case equality as type constraints (nepalez)
711
+
712
+ ## [0.3.3] [2016-05-28]
713
+
714
+ - Add deprecation warnings about modules and case equality as type constraints (nepalez)
715
+
716
+ ## [0.3.2] [2016-05-25]
717
+
718
+ ### Fixed
719
+ - Add explicit requirement for ruby 'set' (rickenharp)
720
+
721
+ ## [0.3.1] [2016-05-22]
722
+
723
+ ### Added
724
+ - Support for tolerance to unknown options (nepalez)
725
+
726
+ ## [0.3.0] [2016-05-19]
727
+
728
+ Breaks interface for adding new plugins. Register new plugin via:
729
+
730
+ ```
731
+ def self.extended(klass)
732
+ klass.register_initializer_plugin NewPlugin
733
+ end
734
+ ```
735
+
736
+ instead of:
737
+
738
+ ```
739
+ def self.extended(klass)
740
+ klass.initializer_builder.register NewPlugin
741
+ end
742
+ ```
743
+
744
+ While the private method ##initializer_builder is still accessible
745
+ its method #register doesn't mutate the builder instance.
746
+
747
+ ### Changed (backward-incompatible changes)
748
+ - Made Mixin##initializer_builder method private (nepalez)
749
+ - Add Mixin#register_initializer_plugin(plugin) method (nepalez)
750
+
751
+ ### Fixed
752
+ - Prevent plugin's registry from polluting superclass (nepalez)
753
+
754
+ ### Changed
755
+ - Make all instances (Builder and Signature) immutable (nepalez)
756
+ - Decouple mixin from a builder to prevent pollution (nepalez)
757
+ - Ensure default value block can use private variables (jeremyf)
758
+
759
+ ## [0.2.1] [2016-05-19]
760
+
761
+ ### Fixed
762
+ - Fix polluting superclass with declarations from subclass (nepalez)
763
+
764
+ ### Changed
765
+ - Make all instances (Builder and Signature) immutable (nepalez)
766
+ - Decouple mixin from a builder to prevent pollution (nepalez)
767
+ - Ensure default value block can use private variables (jeremyf)
768
+
769
+ ## [0.2.0] [2016-05-16]
770
+
771
+ The gem internals has been rewritten heavily to make the gem pluggable and fix
772
+ bugs in "container style". Type constraints were extracted to a plugin
773
+ that should be added explicitly.
774
+
775
+ Small extensions were added to type constraints to support constraint by any
776
+ object, and apply value coercion via `dry-types`.
777
+
778
+ Default assignments became slower (while plain type constraint are not)!
779
+
780
+ ### Changed (backward-incompatible changes)
781
+ - Make dry-types constraint to coerce variables (nepalez)
782
+
783
+ ```ruby
784
+ # This will coerce `name: :foo` to `"foo"`
785
+ option :name, type: Dry::Types::Coercible::String
786
+ ```
787
+
788
+ - Stop supporing proc type constraint (nepalez)
789
+
790
+ ```ruby
791
+ option :name, type: ->(v) { String === v } # this does NOT work any more
792
+ ```
793
+
794
+ later it will be implemented via coercion plugin (not added by default):
795
+
796
+ ```ruby
797
+ require 'dry/initializer/coercion'
798
+
799
+ class MyClass
800
+ extend Dry::Initializer::Mixin
801
+ extend Dry::Initializer::Coercion
802
+
803
+ option :name, coercer: ->(v) { (String === v) ? v.to_sym : fail }
804
+ end
805
+ ```
806
+
807
+ ### Added
808
+ - Support type constraint via every object's case equality (nepalez)
809
+
810
+ ```ruby
811
+ option :name, type: /foo/
812
+ option :name, type: (1...14)
813
+ ```
814
+
815
+ - Support defaults and type constraints for the "container" syntax (nepalez)
816
+ - Support adding extensions via plugin system (nepalez)
817
+
818
+ ### Internal
819
+ - Private method `##__after_initialize__` is added by the `Mixin` along with `#initialize` (nepalez)
820
+
821
+ The previous implementation required defaults and types to be stored in the class method `.initializer_builder`.
822
+ That made "container" syntax to support neither defaults nor types.
823
+
824
+ Now the `#initializer` is still defined via `instance_eval(code)` for efficiency. Some operations
825
+ (like default assignments, coercions, dry-type constraints etc.) cannot be implemented in this way.
826
+ They are made inside `##__after_initialize__` callback, that is biult via `default_method(&block)`
827
+ using instance evals.
828
+
829
+ ## [0.1.1] [2016-04-28]
830
+
831
+ ### Added
832
+ - `include Dry::Initializer.define -> do ... end` syntax (flash-gordon)
833
+
834
+ ## [0.1.0] [2016-04-26]
835
+
836
+ Class DSL splitted to mixin and container versions (thanks to @AMHOL for the idea).
837
+ Backward compatibility is broken.
838
+
839
+ ### Changed (backward-incompatible changes)
840
+ - Use `extend Dry::Initializer::Mixin` instead of `extend Dry::Initializer` (nepalez)
841
+
842
+ ### Added
843
+ - Use `include Dry::Initializer.define(&block)` as an alternative to extending the class (nepalez)
844
+
845
+ ## [0.0.1] [2016-04-09]
846
+
847
+ First public release
848
+
849
+ [0.1.0]: https://github.com/dry-rb/dry-initializer/compare/v0.0.1...v0.1.0
850
+ [0.1.1]: https://github.com/dry-rb/dry-initializer/compare/v0.1.0...v0.1.1
851
+ [0.2.0]: https://github.com/dry-rb/dry-initializer/compare/v0.1.1...v0.2.0
852
+ [0.2.1]: https://github.com/dry-rb/dry-initializer/compare/v0.2.0...v0.2.1
853
+ [0.2.1]: https://github.com/dry-rb/dry-initializer/compare/v0.2.0...v0.2.1
854
+ [0.3.0]: https://github.com/dry-rb/dry-initializer/compare/v0.2.1...v0.3.0
855
+ [0.3.1]: https://github.com/dry-rb/dry-initializer/compare/v0.3.0...v0.3.1
856
+ [0.3.2]: https://github.com/dry-rb/dry-initializer/compare/v0.3.1...v0.3.2
857
+ [0.3.3]: https://github.com/dry-rb/dry-initializer/compare/v0.3.2...v0.3.3
858
+ [0.4.0]: https://github.com/dry-rb/dry-initializer/compare/v0.3.3...v0.4.0
859
+ [0.5.0]: https://github.com/dry-rb/dry-initializer/compare/v0.4.0...v0.5.0
860
+ [0.6.0]: https://github.com/dry-rb/dry-initializer/compare/v0.5.0...v0.6.0
861
+ [0.7.0]: https://github.com/dry-rb/dry-initializer/compare/v0.6.0...v0.7.0
862
+ [0.8.0]: https://github.com/dry-rb/dry-initializer/compare/v0.7.0...v0.8.0
863
+ [0.8.1]: https://github.com/dry-rb/dry-initializer/compare/v0.8.0...v0.8.1
864
+ [0.9.0]: https://github.com/dry-rb/dry-initializer/compare/v0.8.1...v0.9.0
865
+ [0.9.1]: https://github.com/dry-rb/dry-initializer/compare/v0.9.0...v0.9.1
866
+ [0.9.2]: https://github.com/dry-rb/dry-initializer/compare/v0.9.1...v0.9.2
867
+ [0.9.3]: https://github.com/dry-rb/dry-initializer/compare/v0.9.2...v0.9.3
868
+ [0.10.0]: https://github.com/dry-rb/dry-initializer/compare/v0.9.3...v0.10.0
869
+ [0.10.1]: https://github.com/dry-rb/dry-initializer/compare/v0.10.0...v0.10.1
870
+ [0.10.2]: https://github.com/dry-rb/dry-initializer/compare/v0.10.1...v0.10.2
871
+ [0.11.0]: https://github.com/dry-rb/dry-initializer/compare/v0.10.2...v0.11.0
872
+ [1.0.0]: https://github.com/dry-rb/dry-initializer/compare/v0.11.0...v1.0.0
873
+ [1.1.0]: https://github.com/dry-rb/dry-initializer/compare/v1.0.0...v1.1.0
874
+ [1.1.1]: https://github.com/dry-rb/dry-initializer/compare/v1.1.0...v1.1.1
875
+ [1.1.2]: https://github.com/dry-rb/dry-initializer/compare/v1.1.1...v1.1.2
876
+ [1.1.3]: https://github.com/dry-rb/dry-initializer/compare/v1.1.2...v1.1.3
877
+ [1.2.0]: https://github.com/dry-rb/dry-initializer/compare/v1.1.3...v1.2.0
878
+ [1.3.0]: https://github.com/dry-rb/dry-initializer/compare/v1.2.0...v1.3.0
879
+ [1.4.0]: https://github.com/dry-rb/dry-initializer/compare/v1.3.0...v1.4.0
880
+ [1.4.1]: https://github.com/dry-rb/dry-initializer/compare/v1.4.0...v1.4.1
881
+ [2.0.0]: https://github.com/dry-rb/dry-initializer/compare/v1.4.1...v2.0.0
882
+ [2.1.0]: https://github.com/dry-rb/dry-initializer/compare/v2.0.0...v2.1.0
883
+ [2.2.0]: https://github.com/dry-rb/dry-initializer/compare/v2.1.0...v2.2.0
884
+ [2.3.0]: https://github.com/dry-rb/dry-initializer/compare/v2.2.0...v2.3.0
885
+ [2.4.0]: https://github.com/dry-rb/dry-initializer/compare/v2.3.0...v2.4.0
886
+ [2.6.0]: https://github.com/dry-rb/dry-initializer/compare/v2.4.0...v2.5.0
887
+ [2.6.0]: https://github.com/dry-rb/dry-initializer/compare/v2.5.0...v2.6.0
888
+ [3.0.0]: https://github.com/dry-rb/dry-initializer/compare/v2.5.0...v3.0.0
889
+ [3.0.1]: https://github.com/dry-rb/dry-initializer/compare/v3.0.0...v3.0.1
890
+ [3.0.2]: https://github.com/dry-rb/dry-initializer/compare/v3.0.1...v3.0.2