dry-initializer 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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