dry-schema 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +134 -113
- data/README.md +3 -1
- data/lib/dry/schema/constants.rb +3 -2
- data/lib/dry/schema/dsl.rb +63 -16
- data/lib/dry/schema/macros/dsl.rb +16 -5
- data/lib/dry/schema/macros/filled.rb +0 -1
- data/lib/dry/schema/macros/key.rb +0 -1
- data/lib/dry/schema/message_compiler.rb +2 -1
- data/lib/dry/schema/messages/abstract.rb +32 -11
- data/lib/dry/schema/messages/namespaced.rb +1 -1
- data/lib/dry/schema/messages/yaml.rb +12 -0
- data/lib/dry/schema/predicate_registry.rb +2 -23
- data/lib/dry/schema/processor.rb +8 -25
- data/lib/dry/schema/processor_steps.rb +101 -0
- data/lib/dry/schema/version.rb +1 -1
- metadata +5 -5
- data/lib/dry/schema/primitive_inferrer.rb +0 -99
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bf30b15bfb1d11c70a14898fe9ac7d9cb74f46f70b5a26b1e08cf6568414160
|
4
|
+
data.tar.gz: fcd0fc1691ffe1e2b2f5129710fa920daf7ec968749625e050fba3ee9a2a7f73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d5a852339e072be3b033268ed826d75a319cf0c33f279e507fc80d6a3ba079370bd7e2859d3aaa5dba786e85521f9c328cf5107f941fa05f422d0bd1a8250af
|
7
|
+
data.tar.gz: f1e95d4206bc7f45ccc8a5018c14f52f20db4c314509d2eedf72a67284cd574f43ee8d73ec071b7325be0512b87269043d1d488ab63c437fd767032907b0183f
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,29 @@
|
|
1
|
+
# 1.4.0 2019-10-08
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
- Support for passing multiple parent schemas. They are inherited from left to right (@ianwhite)
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
Dry::Schema.define(parent: [parent_a, parent_b, parent_c]) do
|
9
|
+
...
|
10
|
+
end
|
11
|
+
```
|
12
|
+
|
13
|
+
- Improved error messages about missing translations (@skryukov)
|
14
|
+
- [experimental] before/after callbacks for schema steps (@skryukov)
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
- Added/fixed support for custom optional types (@flash-gordon)
|
19
|
+
|
20
|
+
[Compare v1.3.4...v1.4.0](https://github.com/dry-rb/dry-schema/compare/v1.3.4...v1.4.0)
|
21
|
+
|
1
22
|
# 1.3.4 2019-09-11
|
2
23
|
|
3
24
|
### Fixed
|
4
25
|
|
5
|
-
|
26
|
+
- Fixed regression where using `array?` predicate within a block would crach (issue #186) (@skryukov)
|
6
27
|
|
7
28
|
[Compare v1.3.3...v1.3.4](https://github.com/dry-rb/dry-schema/compare/v1.3.3...v1.3.4)
|
8
29
|
|
@@ -10,10 +31,10 @@
|
|
10
31
|
|
11
32
|
### Fixed
|
12
33
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
34
|
+
- Reject attempts to build a nested schema for array types built on `Dry::Types::Nominal` (fixed #171) (@flash-gordon)
|
35
|
+
- Current `I18n.locale` is now properly handled when caching message templates (@flash-gordon)
|
36
|
+
- Default processor uses strict types by default, which fixes various cases when `maybe` is used with a constructor type (@flash-gordon)
|
37
|
+
- Namespaced messages no longer causes a crash when used with nested schemas (fixed #176) (@solnic)
|
17
38
|
|
18
39
|
[Compare v1.3.2...v1.3.3](https://github.com/dry-rb/dry-schema/compare/v1.3.2...v1.3.3)
|
19
40
|
|
@@ -21,7 +42,7 @@
|
|
21
42
|
|
22
43
|
### Added
|
23
44
|
|
24
|
-
|
45
|
+
- Support for new predicates: `bytesize?`, `min_bytesize?` and `max_bytesize?` (@bmalinconico)
|
25
46
|
|
26
47
|
[Compare v1.3.1...v1.3.2](https://github.com/dry-rb/dry-schema/compare/v1.3.1...v1.3.2)
|
27
48
|
|
@@ -29,8 +50,8 @@
|
|
29
50
|
|
30
51
|
### Fixed
|
31
52
|
|
32
|
-
|
33
|
-
|
53
|
+
- `Result#error?` works correctly with nested hashes and arrays (@solnic)
|
54
|
+
- `:hints` extension no longer causes a crash where base messages are generated too (issue #165) (@solnic)
|
34
55
|
|
35
56
|
[Compare v1.3.0...v1.3.1](https://github.com/dry-rb/dry-schema/compare/v1.3.0...v1.3.1)
|
36
57
|
|
@@ -40,15 +61,15 @@
|
|
40
61
|
|
41
62
|
- Automatic predicate inferring for constrained types! (@flash-gordon)
|
42
63
|
|
43
|
-
|
44
|
-
|
64
|
+
```ruby
|
65
|
+
Types::Name = Types::String.constrained(min_size: 1)
|
45
66
|
|
46
|
-
|
47
|
-
|
48
|
-
|
67
|
+
schema = Dry::Schema.define do
|
68
|
+
required(:name).value(Types::Name)
|
69
|
+
end
|
49
70
|
|
50
|
-
|
51
|
-
|
71
|
+
schema.(name: '').errors.to_h # => { name: ["size cannot be less than 1"] }
|
72
|
+
```
|
52
73
|
|
53
74
|
- Support for redefining re-used schemas (issue #43) (@skryukov)
|
54
75
|
|
@@ -64,19 +85,19 @@
|
|
64
85
|
|
65
86
|
- Ability to configure your own type container (@Morozzzko)
|
66
87
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
88
|
+
```ruby
|
89
|
+
types = Dry::Schema::TypeContainer.new
|
90
|
+
types.register(
|
91
|
+
'params.trimmed_string',
|
92
|
+
Types::String.constructor(&:strip).constructor(&:downcase)
|
93
|
+
)
|
73
94
|
|
74
|
-
|
75
|
-
|
95
|
+
Dry::Schema.Params do
|
96
|
+
config.types = types
|
76
97
|
|
77
|
-
|
78
|
-
|
79
|
-
|
98
|
+
require(:name).value(:trimmed_string)
|
99
|
+
end
|
100
|
+
```
|
80
101
|
|
81
102
|
### Fixed
|
82
103
|
|
@@ -98,18 +119,18 @@
|
|
98
119
|
|
99
120
|
### Added
|
100
121
|
|
101
|
-
- `config.messages.default_locale` for setting...default locale (surprise, surprise) (solnic)
|
102
|
-
- `Config` exposes `predicates` setting too (solnic)
|
122
|
+
- `config.messages.default_locale` for setting...default locale (surprise, surprise) (@solnic)
|
123
|
+
- `Config` exposes `predicates` setting too (@solnic)
|
103
124
|
|
104
125
|
### Fixed
|
105
126
|
|
106
|
-
- `filled` macro behavior results in `must be filled` error messages when appropriate - see PR #141 for more information (issue #134) (solnic)
|
107
|
-
- Filter rules no longer cause keys to be added to input (issue #142) (solnic)
|
108
|
-
- Filter rules work now with inheritance (solnic)
|
109
|
-
- Inherited type schemas used by coercion are now properly configured as `lax` type (solnic)
|
110
|
-
- `Config` is now finalized before instantiating schemas and properly dupped when its inherited (flash-gordon + solnic)
|
111
|
-
- `Config#eql?` works as expected (solnic)
|
112
|
-
- Predicates are properly inferred from array with a member type spec, ie `array[:integer]` results in `array? + each(:integer?)` (issue #140) (solnic)
|
127
|
+
- `filled` macro behavior results in `must be filled` error messages when appropriate - see PR #141 for more information (issue #134) (@solnic)
|
128
|
+
- Filter rules no longer cause keys to be added to input (issue #142) (@solnic)
|
129
|
+
- Filter rules work now with inheritance (@solnic)
|
130
|
+
- Inherited type schemas used by coercion are now properly configured as `lax` type (@solnic)
|
131
|
+
- `Config` is now finalized before instantiating schemas and properly dupped when its inherited (@flash-gordon + @solnic)
|
132
|
+
- `Config#eql?` works as expected (@solnic)
|
133
|
+
- Predicates are properly inferred from array with a member type spec, ie `array[:integer]` results in `array? + each(:integer?)` (issue #140) (@solnic)
|
113
134
|
|
114
135
|
[Compare v1.0.3...v1.1.0](https://github.com/dry-rb/dry-schema/compare/v1.0.3...v1.1.0)
|
115
136
|
|
@@ -117,9 +138,9 @@
|
|
117
138
|
|
118
139
|
### Fixed
|
119
140
|
|
120
|
-
- `Object#hash` is no longer used to calculate cache keys due to a potential risk of having hash collisions (solnic)
|
121
|
-
- Predicate arguments are used again for template cache keys (solnic)
|
122
|
-
- `I18n` messages backend no longer evaluates templates twice (solnic)
|
141
|
+
- `Object#hash` is no longer used to calculate cache keys due to a potential risk of having hash collisions (@solnic)
|
142
|
+
- Predicate arguments are used again for template cache keys (@solnic)
|
143
|
+
- `I18n` messages backend no longer evaluates templates twice (@solnic)
|
123
144
|
|
124
145
|
[Compare v1.0.2...v1.0.3](https://github.com/dry-rb/dry-schema/compare/v1.0.2...v1.0.3)
|
125
146
|
|
@@ -127,7 +148,7 @@
|
|
127
148
|
|
128
149
|
### Fixed
|
129
150
|
|
130
|
-
- Caching message templates uses restricted set of known keys to calculate cache keys (issue #132) (solnic)
|
151
|
+
- Caching message templates uses restricted set of known keys to calculate cache keys (issue #132) (@solnic)
|
131
152
|
|
132
153
|
[Compare v1.0.1...v1.0.2](https://github.com/dry-rb/dry-schema/compare/v1.0.1...v1.0.2)
|
133
154
|
|
@@ -135,7 +156,7 @@
|
|
135
156
|
|
136
157
|
### Fixed
|
137
158
|
|
138
|
-
- Applying `key?` predicate no longer causes recursive calls to `Result#errors` (issue #130) (solnic)
|
159
|
+
- Applying `key?` predicate no longer causes recursive calls to `Result#errors` (issue #130) (@solnic)
|
139
160
|
|
140
161
|
[Compare v1.0.0...v1.0.1](https://github.com/dry-rb/dry-schema/compare/v1.0.0...v1.0.1)
|
141
162
|
|
@@ -143,12 +164,12 @@
|
|
143
164
|
|
144
165
|
### Changed
|
145
166
|
|
146
|
-
- [BREAKING] `Result#to_hash` was removed (solnic)
|
167
|
+
- [BREAKING] `Result#to_hash` was removed (@solnic)
|
147
168
|
|
148
169
|
### Fixed
|
149
170
|
|
150
|
-
- Setting `:any` as the type spec no longer crashes (solnic)
|
151
|
-
- `Result#error?` handles paths to array elements correctly (solnic)
|
171
|
+
- Setting `:any` as the type spec no longer crashes (@solnic)
|
172
|
+
- `Result#error?` handles paths to array elements correctly (@solnic)
|
152
173
|
|
153
174
|
[Compare v0.6.0...v1.0.0](https://github.com/dry-rb/dry-schema/compare/v0.6.0...v1.0.0)
|
154
175
|
|
@@ -156,9 +177,9 @@
|
|
156
177
|
|
157
178
|
### Changed
|
158
179
|
|
159
|
-
- Dependency on `dry-types` was bumped to `~> 1.0` (solnic)
|
160
|
-
- Dependency on `dry-logic` was bumped to `~> 1.0` (solnic)
|
161
|
-
- Dependency on `dry-initializer` was bumped to `~> 3.0` (solnic)
|
180
|
+
- Dependency on `dry-types` was bumped to `~> 1.0` (@solnic)
|
181
|
+
- Dependency on `dry-logic` was bumped to `~> 1.0` (@solnic)
|
182
|
+
- Dependency on `dry-initializer` was bumped to `~> 3.0` (@solnic)
|
162
183
|
|
163
184
|
[Compare v0.5.1...v0.6.0](https://github.com/dry-rb/dry-schema/compare/v0.5.1...v0.6.0)
|
164
185
|
|
@@ -166,7 +187,7 @@
|
|
166
187
|
|
167
188
|
### Fixed
|
168
189
|
|
169
|
-
- Key map no longer crashes on unexpected input (issue #118) (solnic)
|
190
|
+
- Key map no longer crashes on unexpected input (issue #118) (@solnic)
|
170
191
|
|
171
192
|
[Compare v0.5.0...v0.5.1](https://github.com/dry-rb/dry-schema/compare/v0.5.0...v0.5.1)
|
172
193
|
|
@@ -176,38 +197,38 @@
|
|
176
197
|
|
177
198
|
- Support for arbitrary meta-data in messages, ie:
|
178
199
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
200
|
+
```yaml
|
201
|
+
en:
|
202
|
+
dry_schema:
|
203
|
+
errors:
|
204
|
+
filled?:
|
205
|
+
text: "cannot be blank"
|
206
|
+
code: 123
|
207
|
+
```
|
187
208
|
|
188
|
-
|
209
|
+
Now your error hash will include `{ foo: [{ text: 'cannot be blank', code: 123 }] }` (@solnic + @flash-gordon)
|
189
210
|
|
190
|
-
- Support for type specs in `array` macro, ie `required(:tags).array(:integer)` (solnic)
|
191
|
-
- Support for type specs in `each` macro, ie `required(:tags).each(:integer)` (solnic)
|
211
|
+
- Support for type specs in `array` macro, ie `required(:tags).array(:integer)` (@solnic)
|
212
|
+
- Support for type specs in `each` macro, ie `required(:tags).each(:integer)` (@solnic)
|
192
213
|
- Shortcut for defining an array with hash as its member, ie:
|
193
214
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
215
|
+
```ruby
|
216
|
+
Dry::Schema.Params do
|
217
|
+
required(:tags).array(:hash) do
|
218
|
+
required(:name).filled(:string)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
```
|
201
222
|
|
202
223
|
### Fixed
|
203
224
|
|
204
|
-
- Inferring predicates doesn't crash when `Any` type is used (flash-gordon)
|
205
|
-
- Inferring type specs when type is already set works correctly (solnic)
|
225
|
+
- Inferring predicates doesn't crash when `Any` type is used (@flash-gordon)
|
226
|
+
- Inferring type specs when type is already set works correctly (@solnic)
|
206
227
|
|
207
228
|
### Changed
|
208
229
|
|
209
|
-
- [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (flash-gordon)
|
210
|
-
- When `:hints` are disabled, result AST will not include hint nodes (solnic)
|
230
|
+
- [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (@flash-gordon)
|
231
|
+
- When `:hints` are disabled, result AST will not include hint nodes (@solnic)
|
211
232
|
|
212
233
|
[Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-schema/compare/v0.4.0...v0.5.0)
|
213
234
|
|
@@ -215,30 +236,30 @@
|
|
215
236
|
|
216
237
|
### Added
|
217
238
|
|
218
|
-
- Schemas are now compatible with procs via `#to_proc` (issue #53) (solnic)
|
219
|
-
- Support for configuring `top_namespace` for localized messages (solnic)
|
220
|
-
- Support for configuring more than one load path for localized messages (solnic)
|
221
|
-
- Support for inferring predicates from arbitrary types (issue #101) (solnic)
|
239
|
+
- Schemas are now compatible with procs via `#to_proc` (issue #53) (@solnic)
|
240
|
+
- Support for configuring `top_namespace` for localized messages (@solnic)
|
241
|
+
- Support for configuring more than one load path for localized messages (@solnic)
|
242
|
+
- Support for inferring predicates from arbitrary types (issue #101) (@solnic)
|
222
243
|
|
223
244
|
### Fixed
|
224
245
|
|
225
|
-
- Handling of messages for `optional` keys without value rules works correctly (issue #87) (solnic)
|
226
|
-
- Message structure for `optional` keys with an array of hashes no longer duplicates keys (issue #89) (solnic)
|
227
|
-
- Inferring `:date_time?` predicate works correctly with `DateTime` types (issue #97) (solnic)
|
246
|
+
- Handling of messages for `optional` keys without value rules works correctly (issue #87) (@solnic)
|
247
|
+
- Message structure for `optional` keys with an array of hashes no longer duplicates keys (issue #89) (@solnic)
|
248
|
+
- Inferring `:date_time?` predicate works correctly with `DateTime` types (issue #97) (@solnic)
|
228
249
|
|
229
250
|
### Changed
|
230
251
|
|
231
|
-
- [BREAKING] Updated to work with `dry-types 0.15.0` (flash-gordon)
|
232
|
-
- [BREAKING] `Result#{errors,messages,hints}` returns `MessageSet` object now which is an enumerable coercible to a hash (solnic)
|
233
|
-
- [BREAKING] `Messages` backend classes no longer use global configuration (solnic)
|
234
|
-
- [BREAKING] Passing a non-symbol key name in the DSL will raise `ArgumentError` (issue #29) (solnic)
|
252
|
+
- [BREAKING] Updated to work with `dry-types 0.15.0` (@flash-gordon)
|
253
|
+
- [BREAKING] `Result#{errors,messages,hints}` returns `MessageSet` object now which is an enumerable coercible to a hash (@solnic)
|
254
|
+
- [BREAKING] `Messages` backend classes no longer use global configuration (@solnic)
|
255
|
+
- [BREAKING] Passing a non-symbol key name in the DSL will raise `ArgumentError` (issue #29) (@solnic)
|
235
256
|
- [BREAKING] Configuration for message backends is now nested under `messages` key with following settings:
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
- [BREAKING] `Messages::I18n` uses `I18.store_translations` instead of messing with `I18n.load_path` (solnic)
|
241
|
-
- Schemas (`Params` and `JSON`) have nicer inspect (solnic)
|
257
|
+
- `messages.backend` - previously `messages`
|
258
|
+
- `messages.load_paths` - previously `messages_path`
|
259
|
+
- `messages.namespace` - previously `namespace`
|
260
|
+
- `messages.top_namespace` - **new setting** see above
|
261
|
+
- [BREAKING] `Messages::I18n` uses `I18.store_translations` instead of messing with `I18n.load_path` (@solnic)
|
262
|
+
- Schemas (`Params` and `JSON`) have nicer inspect (@solnic)
|
242
263
|
|
243
264
|
[Compare v0.3.0...v0.4.0](https://github.com/dry-rb/dry-schema/compare/v0.3.0...v0.4.0)
|
244
265
|
|
@@ -246,16 +267,16 @@
|
|
246
267
|
|
247
268
|
### Fixed
|
248
269
|
|
249
|
-
- Configuration is properly inherited from a parent schema (skryukov)
|
250
|
-
- `Result#error?` returns `true` when a preceding key has errors (solnic)
|
251
|
-
- Predicate inferrer no longer chokes on sum, constructor and enum types (solnic)
|
252
|
-
- Predicate inferrer infers `:bool?` from boolean types (solnic)
|
253
|
-
- Block-based definitions using `array` works correctly (solnic)
|
254
|
-
- Using a disjunction with `array` and `hash` produces correct errors when element validation for array failed (solnic)
|
270
|
+
- Configuration is properly inherited from a parent schema (@skryukov)
|
271
|
+
- `Result#error?` returns `true` when a preceding key has errors (@solnic)
|
272
|
+
- Predicate inferrer no longer chokes on sum, constructor and enum types (@solnic)
|
273
|
+
- Predicate inferrer infers `:bool?` from boolean types (@solnic)
|
274
|
+
- Block-based definitions using `array` works correctly (@solnic)
|
275
|
+
- Using a disjunction with `array` and `hash` produces correct errors when element validation for array failed (@solnic)
|
255
276
|
|
256
277
|
### Changed
|
257
278
|
|
258
|
-
- Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (solnic)
|
279
|
+
- Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (@solnic)
|
259
280
|
|
260
281
|
[Compare v0.2.0...v0.3.0](https://github.com/dry-rb/dry-schema/compare/v0.2.0...v0.3.0)
|
261
282
|
|
@@ -263,28 +284,28 @@
|
|
263
284
|
|
264
285
|
### Added
|
265
286
|
|
266
|
-
- New `hash` macro which prepends `hash?` type-check and allows nested schema definition (solnic)
|
267
|
-
- New `array` macro which works like `each` but prepends `array?` type-check (solnic)
|
287
|
+
- New `hash` macro which prepends `hash?` type-check and allows nested schema definition (@solnic)
|
288
|
+
- New `array` macro which works like `each` but prepends `array?` type-check (@solnic)
|
268
289
|
|
269
290
|
### Fixed
|
270
291
|
|
271
|
-
- Rule name translation works correctly with I18n (issue #52) (solnic)
|
272
|
-
- Rule name translation works correctly with namespaced messages (both I18n and plain YAML) (issue #57) (solnic)
|
273
|
-
- Error messages under namespaces are correctly resolved for overridden names (issue #53) (solnic)
|
274
|
-
- Namespaced error messages work correctly when schemas are reused within other schemas (issue #49) (solnic)
|
275
|
-
- Child schema can override inherited rules now (issue #66) (skryukov)
|
276
|
-
- Hints are correctly generated for disjunction that use type-check predicates (issue #24) (solnic)
|
277
|
-
- Hints are correctly generated for nested schemas (issue #26) (solnic)
|
278
|
-
- `filled` macro respects inferred type-check predicates and puts them in front (solnic)
|
279
|
-
- Value coercion works correctly with re-usable nested schemas (issue #25) (solnic)
|
292
|
+
- Rule name translation works correctly with I18n (issue #52) (@solnic)
|
293
|
+
- Rule name translation works correctly with namespaced messages (both I18n and plain YAML) (issue #57) (@solnic)
|
294
|
+
- Error messages under namespaces are correctly resolved for overridden names (issue #53) (@solnic)
|
295
|
+
- Namespaced error messages work correctly when schemas are reused within other schemas (issue #49) (@solnic)
|
296
|
+
- Child schema can override inherited rules now (issue #66) (@skryukov)
|
297
|
+
- Hints are correctly generated for disjunction that use type-check predicates (issue #24) (@solnic)
|
298
|
+
- Hints are correctly generated for nested schemas (issue #26) (@solnic)
|
299
|
+
- `filled` macro respects inferred type-check predicates and puts them in front (@solnic)
|
300
|
+
- Value coercion works correctly with re-usable nested schemas (issue #25) (@solnic)
|
280
301
|
|
281
302
|
### Changed
|
282
303
|
|
283
|
-
- [BREAKING] **Messages are now configured under `dry_schema` namespace by default** (issue #38) (solnic)
|
284
|
-
- [BREAKING] Hints are now an optional feature provided by `:hints` extension, to load it do `Dry::Schema.load_extensions(:hints)` (solnic)
|
285
|
-
- [BREAKING] Hints generation was improved in general, output of `Result#messages` and `Result#hints` changed in some cases (solnic)
|
286
|
-
- [BREAKING] `schema` macro no longer prepends `hash?` check, for this behavior use the new `hash` macro (see #31) (solnic)
|
287
|
-
- [BREAKING] Support for MRI < 2.4 was dropped (solnic)
|
304
|
+
- [BREAKING] **Messages are now configured under `dry_schema` namespace by default** (issue #38) (@solnic)
|
305
|
+
- [BREAKING] Hints are now an optional feature provided by `:hints` extension, to load it do `Dry::Schema.load_extensions(:hints)` (@solnic)
|
306
|
+
- [BREAKING] Hints generation was improved in general, output of `Result#messages` and `Result#hints` changed in some cases (@solnic)
|
307
|
+
- [BREAKING] `schema` macro no longer prepends `hash?` check, for this behavior use the new `hash` macro (see #31) (@solnic)
|
308
|
+
- [BREAKING] Support for MRI < 2.4 was dropped (@solnic)
|
288
309
|
|
289
310
|
[Compare v0.1.1...v0.2.0](https://github.com/dry-rb/dry-schema/compare/v0.1.1...v0.2.0)
|
290
311
|
|
@@ -292,16 +313,16 @@
|
|
292
313
|
|
293
314
|
### Added
|
294
315
|
|
295
|
-
- `Result#error?` supports checking nested errors too ie`result.error?('user.address')` (solnic)
|
316
|
+
- `Result#error?` supports checking nested errors too ie`result.error?('user.address')` (@solnic)
|
296
317
|
|
297
318
|
### Fixed
|
298
319
|
|
299
|
-
- Fix issues with templates and invalid tokens (issue #27) (solnic)
|
300
|
-
- Fix Ruby warnings (flash-gordon)
|
320
|
+
- Fix issues with templates and invalid tokens (issue #27) (@solnic)
|
321
|
+
- Fix Ruby warnings (@flash-gordon)
|
301
322
|
|
302
323
|
### Internal
|
303
324
|
|
304
|
-
- Key and value coercers are now equalizable (flash-gordon)
|
325
|
+
- Key and value coercers are now equalizable (@flash-gordon)
|
305
326
|
|
306
327
|
[Compare v0.1.0...v0.1.1](https://github.com/dry-rb/dry-schema/compare/v0.1.0...v0.1.1)
|
307
328
|
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
[gem]: https://rubygems.org/gems/dry-schema
|
2
2
|
[travis]: https://travis-ci.com/dry-rb/dry-schema
|
3
|
+
[actions]: https://github.com/dry-rb/dry-schema/actions
|
3
4
|
[codeclimate]: https://codeclimate.com/github/dry-rb/dry-schema
|
4
5
|
[chat]: https://dry-rb.zulipchat.com
|
5
6
|
[inchpages]: http://inch-ci.org/github/dry-rb/dry-schema
|
@@ -7,7 +8,8 @@
|
|
7
8
|
# dry-schema [][chat]
|
8
9
|
|
9
10
|
[][gem]
|
10
|
-
[][travis]
|
12
|
+
[][actions]
|
11
13
|
[][codeclimate]
|
12
14
|
[][codeclimate]
|
13
15
|
[][inchpages]
|
data/lib/dry/schema/constants.rb
CHANGED
@@ -26,10 +26,11 @@ module Dry
|
|
26
26
|
# An error raised when a localized message cannot be found
|
27
27
|
MissingMessageError = Class.new(StandardError) do
|
28
28
|
# @api private
|
29
|
-
def initialize(path)
|
29
|
+
def initialize(path, paths = [])
|
30
30
|
*rest, rule = path
|
31
31
|
super(<<~STR)
|
32
|
-
Message template for #{rule.inspect} under #{rest.join(DOT).inspect} was not found
|
32
|
+
Message template for #{rule.inspect} under #{rest.join(DOT).inspect} was not found. Searched in:
|
33
|
+
#{paths.map { |string| "\"#{string}\"" }.join("\n")}
|
33
34
|
STR
|
34
35
|
end
|
35
36
|
end
|
data/lib/dry/schema/dsl.rb
CHANGED
@@ -9,6 +9,7 @@ require 'dry/schema/types'
|
|
9
9
|
require 'dry/schema/macros'
|
10
10
|
|
11
11
|
require 'dry/schema/processor'
|
12
|
+
require 'dry/schema/processor_steps'
|
12
13
|
require 'dry/schema/key_map'
|
13
14
|
require 'dry/schema/key_coercer'
|
14
15
|
require 'dry/schema/value_coercer'
|
@@ -64,18 +65,21 @@ module Dry
|
|
64
65
|
# @return [Compiler] A key=>type map defined within the DSL
|
65
66
|
option :types, default: -> { EMPTY_HASH.dup }
|
66
67
|
|
67
|
-
# @return [
|
68
|
-
option :parent,
|
68
|
+
# @return [Array] Optional parent DSL objects, that will be used to merge keys and rules
|
69
|
+
option :parent, Types::Coercible::Array, default: -> { EMPTY_ARRAY.dup }, as: :parents
|
69
70
|
|
70
71
|
# @return [Config] Configuration object exposed via `#configure` method
|
71
72
|
option :config, optional: true, default: proc { parent ? parent.config.dup : Config.new }
|
72
73
|
|
74
|
+
# @return [ProcessorSteps] Steps for the processor
|
75
|
+
option :steps, default: proc { parent ? parent.steps.dup : ProcessorSteps.new }
|
76
|
+
|
73
77
|
# Build a new DSL object and evaluate provided block
|
74
78
|
#
|
75
79
|
# @param [Hash] options
|
76
80
|
# @option options [Class] :processor The processor type (`Params`, `JSON` or a custom sub-class)
|
77
81
|
# @option options [Compiler] :compiler An instance of a rule compiler (must be compatible with `Schema::Compiler`) (optional)
|
78
|
-
# @option options [DSL] :parent
|
82
|
+
# @option options [Array[DSL]] :parent One or more instances of the parent DSL (optional)
|
79
83
|
# @option options [Config] :config A configuration object (optional)
|
80
84
|
#
|
81
85
|
# @see Schema.define
|
@@ -189,9 +193,10 @@ module Dry
|
|
189
193
|
#
|
190
194
|
# @api private
|
191
195
|
def call
|
192
|
-
steps =
|
193
|
-
steps
|
194
|
-
steps
|
196
|
+
steps[:key_coercer] = key_coercer
|
197
|
+
steps[:value_coercer] = value_coercer
|
198
|
+
steps[:rule_applier] = rule_applier
|
199
|
+
steps[:filter_schema] = filter_schema.rule_applier if filter_rules?
|
195
200
|
|
196
201
|
processor_type.new(schema_dsl: self, steps: steps)
|
197
202
|
end
|
@@ -215,14 +220,54 @@ module Dry
|
|
215
220
|
-> member_type { type_registry['array'].of(resolve_type(member_type)) }
|
216
221
|
end
|
217
222
|
|
223
|
+
# Method allows steps injection to the processor
|
224
|
+
#
|
225
|
+
# @example
|
226
|
+
# before(:rule_applier) do |input|
|
227
|
+
# input.compact
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# @return [DSL]
|
231
|
+
#
|
232
|
+
# @api public
|
233
|
+
def before(key, &block)
|
234
|
+
steps.before(key, &block)
|
235
|
+
self
|
236
|
+
end
|
237
|
+
|
238
|
+
# Method allows steps injection to the processor
|
239
|
+
#
|
240
|
+
# @example
|
241
|
+
# after(:rule_applier) do |input|
|
242
|
+
# input.compact
|
243
|
+
# end
|
244
|
+
#
|
245
|
+
# @return [DSL]
|
246
|
+
#
|
247
|
+
# @api public
|
248
|
+
def after(key, &block)
|
249
|
+
steps.after(key, &block)
|
250
|
+
self
|
251
|
+
end
|
252
|
+
|
253
|
+
# The parent (last from parents) which is used for copying non mergeable configuration
|
254
|
+
#
|
255
|
+
# @return DSL
|
256
|
+
#
|
257
|
+
# @api public
|
258
|
+
def parent
|
259
|
+
@parent ||= parents.last
|
260
|
+
end
|
261
|
+
|
218
262
|
# Return type schema used by the value coercer
|
219
263
|
#
|
220
264
|
# @return [Dry::Types::Safe]
|
221
265
|
#
|
222
266
|
# @api private
|
223
267
|
def type_schema
|
224
|
-
|
225
|
-
|
268
|
+
our_schema = type_registry['hash'].schema(types).lax
|
269
|
+
schemas = [*parents.map(&:type_schema), our_schema]
|
270
|
+
schemas.inject { |result, schema| result.schema(schema.to_a) }
|
226
271
|
end
|
227
272
|
|
228
273
|
# Return a new DSL instance using the same processor type
|
@@ -276,14 +321,18 @@ module Dry
|
|
276
321
|
#
|
277
322
|
# @api private
|
278
323
|
def filter_schema_dsl
|
279
|
-
@filter_schema_dsl ||= new(parent:
|
324
|
+
@filter_schema_dsl ||= new(parent: parent_filter_schemas)
|
280
325
|
end
|
281
326
|
|
282
327
|
# Check if any filter rules were defined
|
283
328
|
#
|
284
329
|
# @api private
|
285
330
|
def filter_rules?
|
286
|
-
|
331
|
+
if instance_variable_defined?('@filter_schema_dsl') && !filter_schema_dsl.macros.empty?
|
332
|
+
return true
|
333
|
+
end
|
334
|
+
|
335
|
+
parents.any?(&:filter_rules?)
|
287
336
|
end
|
288
337
|
|
289
338
|
protected
|
@@ -323,10 +372,8 @@ module Dry
|
|
323
372
|
private
|
324
373
|
|
325
374
|
# @api private
|
326
|
-
def
|
327
|
-
|
328
|
-
|
329
|
-
parent.filter_schema if parent.filter_rules?
|
375
|
+
def parent_filter_schemas
|
376
|
+
parents.select(&:filter_rules?).map(&:filter_schema)
|
330
377
|
end
|
331
378
|
|
332
379
|
# Build a key coercer
|
@@ -380,12 +427,12 @@ module Dry
|
|
380
427
|
|
381
428
|
# @api private
|
382
429
|
def parent_rules
|
383
|
-
parent
|
430
|
+
parents.reduce({}) { |rules, parent| rules.merge(parent.rules) }
|
384
431
|
end
|
385
432
|
|
386
433
|
# @api private
|
387
434
|
def parent_key_map
|
388
|
-
parent
|
435
|
+
parents.reduce([]) { |key_map, parent| parent.key_map + key_map }
|
389
436
|
end
|
390
437
|
end
|
391
438
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/logic/operators'
|
4
|
+
require 'dry/types/predicate_inferrer'
|
5
|
+
require 'dry/types/primitive_inferrer'
|
4
6
|
|
5
7
|
require 'dry/schema/macros/core'
|
6
8
|
|
@@ -26,13 +28,13 @@ module Dry
|
|
26
28
|
# PredicateInferrer is used to infer predicate type-check from a type spec
|
27
29
|
# @return [PredicateInferrer]
|
28
30
|
# @api private
|
29
|
-
option :predicate_inferrer, default: proc { PredicateInferrer.new(compiler.predicates) }
|
31
|
+
option :predicate_inferrer, default: proc { ::Dry::Types::PredicateInferrer.new(compiler.predicates) }
|
30
32
|
|
31
33
|
# @!attribute [r] primitive_inferrer
|
32
34
|
# PrimitiveInferrer used to get a list of primitive classes from configured type
|
33
35
|
# @return [PrimitiveInferrer]
|
34
36
|
# @api private
|
35
|
-
option :primitive_inferrer, default: proc { PrimitiveInferrer.new }
|
37
|
+
option :primitive_inferrer, default: proc { ::Dry::Types::PrimitiveInferrer.new }
|
36
38
|
|
37
39
|
# @overload value(*predicates, **predicate_opts)
|
38
40
|
# Set predicates without and with arguments
|
@@ -198,9 +200,7 @@ module Dry
|
|
198
200
|
predicates = Array(type_spec ? args[1..-1] : args)
|
199
201
|
|
200
202
|
if type_spec
|
201
|
-
resolved_type =
|
202
|
-
nullable && !type_spec.is_a?(::Array) ? [:nil, type_spec] : type_spec
|
203
|
-
)
|
203
|
+
resolved_type = resolve_type(type_spec, nullable)
|
204
204
|
|
205
205
|
type(resolved_type) if set_type
|
206
206
|
|
@@ -213,6 +213,17 @@ module Dry
|
|
213
213
|
|
214
214
|
yield(*predicates, type_spec: type_spec)
|
215
215
|
end
|
216
|
+
|
217
|
+
# @api private
|
218
|
+
def resolve_type(type_spec, nullable)
|
219
|
+
resolved = schema_dsl.resolve_type(type_spec)
|
220
|
+
|
221
|
+
if type_spec.is_a?(::Array) || !nullable || resolved.optional?
|
222
|
+
resolved
|
223
|
+
else
|
224
|
+
schema_dsl.resolve_type([:nil, resolved])
|
225
|
+
end
|
226
|
+
end
|
216
227
|
end
|
217
228
|
end
|
218
229
|
end
|
@@ -130,7 +130,8 @@ module Dry
|
|
130
130
|
path: path.last, **tokens, **lookup_options(arg_vals: arg_vals, input: input)
|
131
131
|
).to_h
|
132
132
|
|
133
|
-
template, meta = messages[predicate, options] ||
|
133
|
+
template, meta = messages[predicate, options] ||
|
134
|
+
raise(MissingMessageError.new(path, messages.looked_up_paths(predicate, options)))
|
134
135
|
|
135
136
|
text = message_text(template, tokens, options)
|
136
137
|
|
@@ -99,23 +99,27 @@ module Dry
|
|
99
99
|
end
|
100
100
|
alias_method :[], :call
|
101
101
|
|
102
|
+
# Retrieve an array of looked up paths
|
103
|
+
#
|
104
|
+
# @param [Symbol] predicate
|
105
|
+
# @param [Hash] options
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
#
|
109
|
+
# @api public
|
110
|
+
def looked_up_paths(predicate, options)
|
111
|
+
tokens = lookup_tokens(predicate, options)
|
112
|
+
filled_lookup_paths(tokens)
|
113
|
+
end
|
114
|
+
|
102
115
|
# Try to find a message for the given predicate and its options
|
103
116
|
#
|
104
117
|
# @api private
|
105
118
|
#
|
106
119
|
# rubocop:disable Metrics/AbcSize
|
107
120
|
def lookup(predicate, options)
|
108
|
-
tokens = options.merge(
|
109
|
-
predicate: predicate,
|
110
|
-
root: options[:not] ? "#{root}.not" : root,
|
111
|
-
arg_type: config.arg_types[options[:arg_type]],
|
112
|
-
val_type: config.val_types[options[:val_type]],
|
113
|
-
message_type: options[:message_type] || :failure
|
114
|
-
)
|
115
|
-
|
116
121
|
opts = options.reject { |k, _| config.lookup_options.include?(k) }
|
117
|
-
|
118
|
-
path = lookup_paths(tokens).detect { |key| key?(key, opts) }
|
122
|
+
path = lookup_paths(predicate, options).detect { |key| key?(key, opts) }
|
119
123
|
|
120
124
|
return unless path
|
121
125
|
|
@@ -130,7 +134,13 @@ module Dry
|
|
130
134
|
# rubocop:enable Metrics/AbcSize
|
131
135
|
|
132
136
|
# @api private
|
133
|
-
def lookup_paths(
|
137
|
+
def lookup_paths(predicate, options)
|
138
|
+
tokens = lookup_tokens(predicate, options)
|
139
|
+
filled_lookup_paths(tokens)
|
140
|
+
end
|
141
|
+
|
142
|
+
# @api private
|
143
|
+
def filled_lookup_paths(tokens)
|
134
144
|
config.lookup_paths.map { |path| path % tokens }
|
135
145
|
end
|
136
146
|
|
@@ -178,6 +188,17 @@ module Dry
|
|
178
188
|
|
179
189
|
private
|
180
190
|
|
191
|
+
# @api private
|
192
|
+
def lookup_tokens(predicate, options)
|
193
|
+
options.merge(
|
194
|
+
predicate: predicate,
|
195
|
+
root: options[:not] ? "#{root}.not" : root,
|
196
|
+
arg_type: config.arg_types[options[:arg_type]],
|
197
|
+
val_type: config.val_types[options[:val_type]],
|
198
|
+
message_type: options[:message_type] || :failure
|
199
|
+
)
|
200
|
+
end
|
201
|
+
|
181
202
|
# @api private
|
182
203
|
def custom_top_namespace?(path)
|
183
204
|
path.to_s == DEFAULT_MESSAGES_PATH.to_s && config.top_namespace != DEFAULT_MESSAGES_ROOT
|
@@ -68,6 +68,18 @@ module Dry
|
|
68
68
|
@t = proc { |key, locale: default_locale| get("%<locale>s.#{key}", locale: locale) }
|
69
69
|
end
|
70
70
|
|
71
|
+
# Get an array of looked up paths
|
72
|
+
#
|
73
|
+
# @param [Symbol] predicate
|
74
|
+
# @param [Hash] options
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
#
|
78
|
+
# @api public
|
79
|
+
def looked_up_paths(predicate, options)
|
80
|
+
super.map { |path| path % { locale: options[:locale] || default_locale } }
|
81
|
+
end
|
82
|
+
|
71
83
|
# Get a message for the given key and its options
|
72
84
|
#
|
73
85
|
# @param [Symbol] key
|
@@ -1,35 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/logic/predicates'
|
4
|
+
require 'dry/types/predicate_registry'
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module Schema
|
7
8
|
# A registry with predicate objects from `Dry::Logic::Predicates`
|
8
9
|
#
|
9
10
|
# @api private
|
10
|
-
class PredicateRegistry
|
11
|
-
# @api private
|
12
|
-
attr_reader :predicates
|
13
|
-
|
14
|
-
# @api private
|
15
|
-
attr_reader :has_predicate
|
16
|
-
|
17
|
-
# @api private
|
18
|
-
def initialize(predicates = Dry::Logic::Predicates)
|
19
|
-
@predicates = predicates
|
20
|
-
@has_predicate = ::Kernel.instance_method(:respond_to?).bind(@predicates)
|
21
|
-
end
|
22
|
-
|
23
|
-
# @api private
|
24
|
-
def [](name)
|
25
|
-
predicates[name]
|
26
|
-
end
|
27
|
-
|
28
|
-
# @api private
|
29
|
-
def key?(name)
|
30
|
-
has_predicate.(name)
|
31
|
-
end
|
32
|
-
|
11
|
+
class PredicateRegistry < Dry::Types::PredicateRegistry
|
33
12
|
# @api private
|
34
13
|
def arg_list(name, *values)
|
35
14
|
predicate = self[name]
|
data/lib/dry/schema/processor.rb
CHANGED
@@ -5,6 +5,7 @@ require 'dry/initializer'
|
|
5
5
|
|
6
6
|
require 'dry/schema/type_registry'
|
7
7
|
require 'dry/schema/type_container'
|
8
|
+
require 'dry/schema/processor_steps'
|
8
9
|
require 'dry/schema/rule_applier'
|
9
10
|
require 'dry/schema/key_coercer'
|
10
11
|
require 'dry/schema/value_coercer'
|
@@ -12,14 +13,9 @@ require 'dry/schema/value_coercer'
|
|
12
13
|
module Dry
|
13
14
|
module Schema
|
14
15
|
# Processes input data using objects configured within the DSL
|
16
|
+
# Processing is split into steps represented by `ProcessorSteps`.
|
15
17
|
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# 1. Prepare input hash using a key map
|
19
|
-
# 2. Apply pre-coercion filtering rules (optional step, used only when `filter` was used)
|
20
|
-
# 3. Apply value coercions based on type specifications
|
21
|
-
# 4. Apply rules
|
22
|
-
#
|
18
|
+
# @see ProcessorSteps
|
23
19
|
# @see Params
|
24
20
|
# @see JSON
|
25
21
|
#
|
@@ -32,7 +28,7 @@ module Dry
|
|
32
28
|
setting :type_registry_namespace, :strict
|
33
29
|
setting :filter_empty_string, false
|
34
30
|
|
35
|
-
option :steps, default: -> {
|
31
|
+
option :steps, default: -> { ProcessorSteps.new }
|
36
32
|
|
37
33
|
option :schema_dsl
|
38
34
|
|
@@ -77,16 +73,6 @@ module Dry
|
|
77
73
|
end
|
78
74
|
end
|
79
75
|
|
80
|
-
# Append a step
|
81
|
-
#
|
82
|
-
# @return [Processor]
|
83
|
-
#
|
84
|
-
# @api private
|
85
|
-
def <<(step)
|
86
|
-
steps << step
|
87
|
-
self
|
88
|
-
end
|
89
|
-
|
90
76
|
# Apply processing steps to the provided input
|
91
77
|
#
|
92
78
|
# @param [Hash] input
|
@@ -96,10 +82,7 @@ module Dry
|
|
96
82
|
# @api public
|
97
83
|
def call(input)
|
98
84
|
Result.new(input, message_compiler: message_compiler) do |result|
|
99
|
-
steps.
|
100
|
-
output = step.(result)
|
101
|
-
result.replace(output) if output.is_a?(::Hash)
|
102
|
-
end
|
85
|
+
steps.call(result)
|
103
86
|
end
|
104
87
|
end
|
105
88
|
alias_method :[], :call
|
@@ -119,7 +102,7 @@ module Dry
|
|
119
102
|
#
|
120
103
|
# @api public
|
121
104
|
def key_map
|
122
|
-
|
105
|
+
steps[:key_coercer].key_map
|
123
106
|
end
|
124
107
|
|
125
108
|
# Return string represntation
|
@@ -139,7 +122,7 @@ module Dry
|
|
139
122
|
#
|
140
123
|
# @api private
|
141
124
|
def type_schema
|
142
|
-
|
125
|
+
steps[:value_coercer].type_schema
|
143
126
|
end
|
144
127
|
|
145
128
|
# Return the rules config
|
@@ -180,7 +163,7 @@ module Dry
|
|
180
163
|
#
|
181
164
|
# @api private
|
182
165
|
def rule_applier
|
183
|
-
|
166
|
+
steps[:rule_applier]
|
184
167
|
end
|
185
168
|
alias_method :to_rule, :rule_applier
|
186
169
|
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/initializer'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Schema
|
7
|
+
# Steps for the Dry::Schema::Processor
|
8
|
+
#
|
9
|
+
# There are 4 main steps:
|
10
|
+
#
|
11
|
+
# 1. `key_coercer` - Prepare input hash using a key map
|
12
|
+
# 2. `filter_schema` - Apply pre-coercion filtering rules
|
13
|
+
# (optional step, used only when `filter` was used)
|
14
|
+
# 3. `value_coercer` - Apply value coercions based on type specifications
|
15
|
+
# 4. `rule_applier` - Apply rules
|
16
|
+
#
|
17
|
+
# @see Processor
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
class ProcessorSteps
|
21
|
+
extend Dry::Initializer
|
22
|
+
|
23
|
+
STEPS_IN_ORDER = %i[key_coercer filter_schema value_coercer rule_applier].freeze
|
24
|
+
|
25
|
+
option :steps, default: -> { EMPTY_HASH.dup }
|
26
|
+
option :before_steps, default: -> { EMPTY_HASH.dup }
|
27
|
+
option :after_steps, default: -> { EMPTY_HASH.dup }
|
28
|
+
|
29
|
+
def call(result)
|
30
|
+
STEPS_IN_ORDER.each do |name|
|
31
|
+
before_steps[name]&.each { |step| process_step(step, result) }
|
32
|
+
process_step(steps[name], result)
|
33
|
+
after_steps[name]&.each { |step| process_step(step, result) }
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return step by name
|
39
|
+
#
|
40
|
+
# @param [Symbol] name The step name
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def [](name)
|
44
|
+
steps[name]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sets step by name
|
48
|
+
#
|
49
|
+
# @param [Symbol] name The step name
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def []=(name, value)
|
53
|
+
validate_step_name(name)
|
54
|
+
steps[name] = value
|
55
|
+
end
|
56
|
+
|
57
|
+
# Add passed block before mentioned step
|
58
|
+
#
|
59
|
+
# @param [Symbol] name The step name
|
60
|
+
#
|
61
|
+
# @return [ProcessorSteps]
|
62
|
+
#
|
63
|
+
# @api public
|
64
|
+
def after(name, &block)
|
65
|
+
validate_step_name(name)
|
66
|
+
after_steps[name] ||= EMPTY_ARRAY.dup
|
67
|
+
after_steps[name] << block.to_proc
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# Add passed block before mentioned step
|
72
|
+
#
|
73
|
+
# @param [Symbol] name The step name
|
74
|
+
#
|
75
|
+
# @return [ProcessorSteps]
|
76
|
+
#
|
77
|
+
# @api public
|
78
|
+
def before(name, &block)
|
79
|
+
validate_step_name(name)
|
80
|
+
before_steps[name] ||= EMPTY_ARRAY.dup
|
81
|
+
before_steps[name] << block.to_proc
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
def process_step(step, result)
|
87
|
+
return unless step
|
88
|
+
|
89
|
+
output = step.(result)
|
90
|
+
result.replace(output) if output.is_a?(::Hash)
|
91
|
+
end
|
92
|
+
|
93
|
+
# @api private
|
94
|
+
def validate_step_name(name)
|
95
|
+
return if STEPS_IN_ORDER.include?(name)
|
96
|
+
|
97
|
+
raise ArgumentError, "Undefined step name #{name}. Available names: #{STEPS_IN_ORDER}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/dry/schema/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -106,14 +106,14 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '1.
|
109
|
+
version: '1.2'
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
112
|
version_requirements: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
114
|
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version: '1.
|
116
|
+
version: '1.2'
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
118
|
name: bundler
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -217,8 +217,8 @@ files:
|
|
217
217
|
- lib/dry/schema/predicate.rb
|
218
218
|
- lib/dry/schema/predicate_inferrer.rb
|
219
219
|
- lib/dry/schema/predicate_registry.rb
|
220
|
-
- lib/dry/schema/primitive_inferrer.rb
|
221
220
|
- lib/dry/schema/processor.rb
|
221
|
+
- lib/dry/schema/processor_steps.rb
|
222
222
|
- lib/dry/schema/result.rb
|
223
223
|
- lib/dry/schema/rule_applier.rb
|
224
224
|
- lib/dry/schema/trace.rb
|
@@ -1,99 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'dry/core/cache'
|
4
|
-
|
5
|
-
module Dry
|
6
|
-
module Schema
|
7
|
-
# PrimitiveInferrer is used internally by `Macros::Filled`
|
8
|
-
# for inferring a list of possible primitives that a given
|
9
|
-
# type can handle.
|
10
|
-
#
|
11
|
-
# @api private
|
12
|
-
class PrimitiveInferrer
|
13
|
-
extend Dry::Core::Cache
|
14
|
-
|
15
|
-
# Compiler reduces type AST into a list of primitives
|
16
|
-
#
|
17
|
-
# @api private
|
18
|
-
class Compiler
|
19
|
-
# @api private
|
20
|
-
def visit(node)
|
21
|
-
meth, rest = node
|
22
|
-
public_send(:"visit_#{meth}", rest)
|
23
|
-
end
|
24
|
-
|
25
|
-
# @api private
|
26
|
-
def visit_nominal(node)
|
27
|
-
type, _ = node
|
28
|
-
type
|
29
|
-
end
|
30
|
-
|
31
|
-
# @api private
|
32
|
-
def visit_hash(_)
|
33
|
-
Hash
|
34
|
-
end
|
35
|
-
alias_method :visit_schema, :visit_hash
|
36
|
-
|
37
|
-
# @api private
|
38
|
-
def visit_array(_)
|
39
|
-
Array
|
40
|
-
end
|
41
|
-
|
42
|
-
# @api private
|
43
|
-
def visit_lax(node)
|
44
|
-
visit(node)
|
45
|
-
end
|
46
|
-
|
47
|
-
# @api private
|
48
|
-
def visit_constructor(node)
|
49
|
-
other, * = node
|
50
|
-
visit(other)
|
51
|
-
end
|
52
|
-
|
53
|
-
# @api private
|
54
|
-
def visit_enum(node)
|
55
|
-
other, * = node
|
56
|
-
visit(other)
|
57
|
-
end
|
58
|
-
|
59
|
-
# @api private
|
60
|
-
def visit_sum(node)
|
61
|
-
left, right = node
|
62
|
-
|
63
|
-
[visit(left), visit(right)].flatten(1)
|
64
|
-
end
|
65
|
-
|
66
|
-
# @api private
|
67
|
-
def visit_constrained(node)
|
68
|
-
other, * = node
|
69
|
-
visit(other)
|
70
|
-
end
|
71
|
-
|
72
|
-
# @api private
|
73
|
-
def visit_any(_)
|
74
|
-
Object
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# @return [Compiler]
|
79
|
-
# @api private
|
80
|
-
attr_reader :compiler
|
81
|
-
|
82
|
-
# @api private
|
83
|
-
def initialize
|
84
|
-
@compiler = Compiler.new
|
85
|
-
end
|
86
|
-
|
87
|
-
# Infer predicate identifier from the provided type
|
88
|
-
#
|
89
|
-
# @return [Symbol]
|
90
|
-
#
|
91
|
-
# @api private
|
92
|
-
def [](type)
|
93
|
-
self.class.fetch_or_store(type.hash) do
|
94
|
-
Array(compiler.visit(type.to_ast)).freeze
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|