dry-schema 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
|
8
9
|
|
9
10
|
[![Gem Version](https://badge.fury.io/rb/dry-schema.svg)][gem]
|
10
|
-
[![
|
11
|
+
[![Travis Status](https://travis-ci.com/dry-rb/dry-schema.svg?branch=master)][travis]
|
12
|
+
[![CI Status](https://github.com/dry-rb/dry-schema/workflows/ci/badge.svg)][actions]
|
11
13
|
[![Code Climate](https://codeclimate.com/github/dry-rb/dry-schema/badges/gpa.svg)][codeclimate]
|
12
14
|
[![Test Coverage](https://codeclimate.com/github/dry-rb/dry-schema/badges/coverage.svg)][codeclimate]
|
13
15
|
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-schema.svg?branch=master)][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
|