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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9efbd58d7d7d70ec01d578de507f1fc6ba3e78bfeb81e30e8b69a2ca29fbc753
4
- data.tar.gz: 874370eec0e97f1b87bee9a18d606a45b0aba4d80729c7637407147f4f01a7fc
3
+ metadata.gz: 8bf30b15bfb1d11c70a14898fe9ac7d9cb74f46f70b5a26b1e08cf6568414160
4
+ data.tar.gz: fcd0fc1691ffe1e2b2f5129710fa920daf7ec968749625e050fba3ee9a2a7f73
5
5
  SHA512:
6
- metadata.gz: 8b23a5b75861ef7f9c9ab8430439f580877788c98f79268913723e9fea653df7aaf3fc074839ce561b42c8f7268f9a22069e0a7c8c3f71b20f9cdd4956df1aad
7
- data.tar.gz: ee1987669c04d04b93d20d1a975c2418b8cf9b355caf96a313f9a7f4b50d60514ec2071af82d263f0972fc3c24c865c3fb67b7073a914a3dce1636ce958ea455
6
+ metadata.gz: 7d5a852339e072be3b033268ed826d75a319cf0c33f279e507fc80d6a3ba079370bd7e2859d3aaa5dba786e85521f9c328cf5107f941fa05f422d0bd1a8250af
7
+ data.tar.gz: f1e95d4206bc7f45ccc8a5018c14f52f20db4c314509d2eedf72a67284cd574f43ee8d73ec071b7325be0512b87269043d1d488ab63c437fd767032907b0183f
@@ -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
- * Fixed regression where using `array?` predicate within a block would crach (issue #186) (@skryukov)
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
- * Reject attempts to build a nested schema for array types built on `Dry::Types::Nominal` (fixed #171) (@flash-gordon)
14
- * Current `I18n.locale` is now properly handled when caching message templates (@flash-gordon)
15
- * Default processor uses strict types by default, which fixes various cases when `maybe` is used with a constructor type (@flash-gordon)
16
- * Namespaced messages no longer causes a crash when used with nested schemas (fixed #176) (@solnic)
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
- * Support for new predicates: `bytesize?`, `min_bytesize?` and `max_bytesize?` (@bmalinconico)
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
- * `Result#error?` works correctly with nested hashes and arrays (@solnic)
33
- * `:hints` extension no longer causes a crash where base messages are generated too (issue #165) (@solnic)
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
- ```ruby
44
- Types::Name = Types::String.constrained(min_size: 1)
64
+ ```ruby
65
+ Types::Name = Types::String.constrained(min_size: 1)
45
66
 
46
- schema = Dry::Schema.define do
47
- required(:name).value(Types::Name)
48
- end
67
+ schema = Dry::Schema.define do
68
+ required(:name).value(Types::Name)
69
+ end
49
70
 
50
- schema.(name: '').errors.to_h # => { name: ["size cannot be less than 1"] }
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
- ```ruby
68
- types = Dry::Schema::TypeContainer.new
69
- types.register(
70
- 'params.trimmed_string',
71
- Types::String.constructor(&:strip).constructor(&:downcase)
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
- Dry::Schema.Params do
75
- config.types = types
95
+ Dry::Schema.Params do
96
+ config.types = types
76
97
 
77
- require(:name).value(:trimmed_string)
78
- end
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
- ```yaml
180
- en:
181
- dry_schema:
182
- errors:
183
- filled?:
184
- text: "cannot be blank"
185
- code: 123
186
- ```
200
+ ```yaml
201
+ en:
202
+ dry_schema:
203
+ errors:
204
+ filled?:
205
+ text: "cannot be blank"
206
+ code: 123
207
+ ```
187
208
 
188
- Now your error hash will include `{ foo: [{ text: 'cannot be blank', code: 123 }] }` (solnic + flash-gordon)
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
- ```ruby
195
- Dry::Schema.Params do
196
- required(:tags).array(:hash) do
197
- required(:name).filled(:string)
198
- end
199
- end
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
- - `messages.backend` - previously `messages`
237
- - `messages.load_paths` - previously `messages_path`
238
- - `messages.namespace` - previously `namespace`
239
- - `messages.top_namespace` - **new setting** see above
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
- [![Build Status](https://travis-ci.com/dry-rb/dry-schema.svg?branch=master)][travis]
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]
@@ -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
@@ -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 [DSL] An optional parent DSL object that will be used to merge keys and rules
68
- option :parent, optional: true
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 An instance of the parent DSL (optional)
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 = [key_coercer]
193
- steps << filter_schema.rule_applier if filter_rules?
194
- steps << value_coercer << rule_applier
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
- schema = type_registry['hash'].schema(types).lax
225
- parent ? parent.type_schema.schema(schema.to_a) : schema
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: parent_filter_schema)
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
- (instance_variable_defined?('@filter_schema_dsl') && !filter_schema_dsl.macros.empty?) || parent&.filter_rules?
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 parent_filter_schema
327
- return unless parent
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&.rules || EMPTY_HASH
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&.key_map || EMPTY_ARRAY
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 = schema_dsl.resolve_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
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/schema/primitive_inferrer'
4
3
  require 'dry/schema/macros/value'
5
4
 
6
5
  module Dry
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/schema/predicate_inferrer'
4
3
  require 'dry/schema/processor'
5
4
  require 'dry/schema/macros/dsl'
6
5
  require 'dry/schema/constants'
@@ -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] || raise(MissingMessageError, path)
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(tokens)
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
@@ -55,7 +55,7 @@ module Dry
55
55
  end
56
56
 
57
57
  # @api private
58
- def lookup_paths(tokens)
58
+ def filled_lookup_paths(tokens)
59
59
  super(tokens.merge(root: "#{tokens[:root]}.#{namespace}")) + super
60
60
  end
61
61
 
@@ -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]
@@ -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
- # Processing is split into 4 main steps:
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: -> { EMPTY_ARRAY.dup }
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.each do |step|
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
- @key_map ||= steps.detect { |s| s.is_a?(KeyCoercer) }.key_map
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
- @type_schema ||= steps.detect { |s| s.is_a?(ValueCoercer) }.type_schema
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
- @rule_applier ||= steps.last
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Schema
5
- VERSION = '1.3.4'
5
+ VERSION = '1.4.0'
6
6
  end
7
7
  end
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.3.4
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-09-11 00:00:00.000000000 Z
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.0'
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.0'
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