dry-schema 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7dce78efba45d06df82c2de21ab9da5208fef746034e1f3aba396221897540d
4
- data.tar.gz: 85f73e374a58a8110a3d75f1617d3b015b07b0d3f9c44caf4dceced1930d88df
3
+ metadata.gz: c2703b501037f07e55a7018b8e0e048525e591d2f5cb5e369717a0635aacd443
4
+ data.tar.gz: e199bafff541bee970435b2dd26ce10b888c2167d5aec919dafbf91b089311ea
5
5
  SHA512:
6
- metadata.gz: b1317319cec5bacf68ec380166226382c4d10818db4b1a575841f04c43b12b2b420877121876ebb13ce85c59b7b88a375c1f9798523cc6fb123e274507203cd2
7
- data.tar.gz: fa995747a3efd66855e6d8cbb7d07e6d2002cd9e459237acc58b8747dd7f7d728d4a5f57482269d25e3c63319110975e8b01ec713536defd31742812dc92e334
6
+ metadata.gz: b7512d9308582c306717a507ad4c218e50137e13699dacadcdb4d9f5d8bb01cfae635cdd78a27d4466e620c13e43d63b4cc7f27112d1bbaf74bdc5e7c7e1d384
7
+ data.tar.gz: 58bc3d577e79752c8495749af8dc9304d1bcae753f6a612fbf744f4dc9586a65aafceb038c9ec6198361edd0b7f930e8f59abd600c74b3ba562de32a5d967e70
@@ -1,22 +1,60 @@
1
+ # 1.3.0 2019-07-06
2
+
3
+ ### Added
4
+
5
+ - Automatic predicate inferring for constrained types! (@flash-gordon)
6
+
7
+ ```ruby
8
+ Types::Name = Types::String.constrained(min_size: 1)
9
+
10
+ schema = Dry::Schema.define do
11
+ required(:name).value(Types::Name)
12
+ end
13
+
14
+ schema.(name: '').errors.to_h # => { name: ["size cannot be less than 1"] }
15
+ ```
16
+
17
+ - Support for redefining re-used schemas (issue #43) (@skryukov)
18
+
19
+ ### Fixed
20
+
21
+ - Type container is passed down to nested schemas (@flash-gordon)
22
+
23
+ [Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-schema/compare/v1.2.0...v1.3.0)
24
+
1
25
  # v1.2.0 2019-06-13
2
26
 
3
27
  ### Added
4
28
 
5
- * Ability to configure your own type container (@Morozzzko)
29
+ - Ability to configure your own type container (@Morozzzko)
30
+
31
+ ```ruby
32
+ types = Dry::Schema::TypeContainer.new
33
+ types.register(
34
+ 'params.trimmed_string',
35
+ Types::String.constructor(&:strip).constructor(&:downcase)
36
+ )
37
+
38
+ Dry::Schema.Params do
39
+ config.types = types
40
+
41
+ require(:name).value(:trimmed_string)
42
+ end
43
+ ```
6
44
 
7
45
  ### Fixed
8
46
 
9
- * `filled` macro no longer generates incorrect messages for arrays (issue #151) (@solnic)
10
- * `filled` macro works correctly with constructor types (@solnic)
11
- * `filled` works correctly with nested schemas (#149) (@solnic + @timriley)
12
- * Custom array constructors are no longer discredited by `array` macro (@solnic)
13
- * `BigDecimal` type is correctly handled by predicate inference (@solnic)
14
- * Works with latest `dry-logic` which provides the new `respond_to?` predicate (#153) (@flash-gordon)
47
+ - `filled` macro no longer generates incorrect messages for arrays (issue #151) (@solnic)
48
+ - `filled` macro works correctly with constructor types (@solnic)
49
+ - `filled` works correctly with nested schemas (#149) (@solnic + @timriley)
50
+ - Custom array constructors are no longer discredited by `array` macro (@solnic)
51
+ - `BigDecimal` type is correctly handled by predicate inference (@solnic)
52
+ - Works with latest `dry-logic` which provides the new `respond_to?` predicate (#153) (@flash-gordon)
15
53
 
16
54
  ### Changed
17
55
 
18
- * Fixes related to `filled` restored pre-1.1.0 behavior of `:hints` which are again included (@solnic)
19
- * `filled` no longer uses filter rules to handle empty strings in `Params` (@solnic)
56
+ - Fixes related to `filled` restored pre-1.1.0 behavior of `:hints` which are again included (@solnic)
57
+ - `filled` no longer uses filter rules to handle empty strings in `Params` (@solnic)
20
58
 
21
59
  [Compare v1.1.0...v1.2.0](https://github.com/dry-rb/dry-schema/compare/v1.1.0...v1.2.0)
22
60
 
@@ -24,18 +62,18 @@
24
62
 
25
63
  ### Added
26
64
 
27
- * `config.messages.default_locale` for setting...default locale (surprise, surprise) (solnic)
28
- * `Config` exposes `predicates` setting too (solnic)
65
+ - `config.messages.default_locale` for setting...default locale (surprise, surprise) (solnic)
66
+ - `Config` exposes `predicates` setting too (solnic)
29
67
 
30
68
  ### Fixed
31
69
 
32
- * `filled` macro behavior results in `must be filled` error messages when appropriate - see PR #141 for more information (issue #134) (solnic)
33
- * Filter rules no longer cause keys to be added to input (issue #142) (solnic)
34
- * Filter rules work now with inheritance (solnic)
35
- * Inherited type schemas used by coercion are now properly configured as `lax` type (solnic)
36
- * `Config` is now finalized before instantiating schemas and properly dupped when its inherited (flash-gordon + solnic)
37
- * `Config#eql?` works as expected (solnic)
38
- * Predicates are properly inferred from array with a member type spec, ie `array[:integer]` results in `array? + each(:integer?)` (issue #140) (solnic)
70
+ - `filled` macro behavior results in `must be filled` error messages when appropriate - see PR #141 for more information (issue #134) (solnic)
71
+ - Filter rules no longer cause keys to be added to input (issue #142) (solnic)
72
+ - Filter rules work now with inheritance (solnic)
73
+ - Inherited type schemas used by coercion are now properly configured as `lax` type (solnic)
74
+ - `Config` is now finalized before instantiating schemas and properly dupped when its inherited (flash-gordon + solnic)
75
+ - `Config#eql?` works as expected (solnic)
76
+ - Predicates are properly inferred from array with a member type spec, ie `array[:integer]` results in `array? + each(:integer?)` (issue #140) (solnic)
39
77
 
40
78
  [Compare v1.0.3...v1.1.0](https://github.com/dry-rb/dry-schema/compare/v1.0.3...v1.1.0)
41
79
 
@@ -43,9 +81,9 @@
43
81
 
44
82
  ### Fixed
45
83
 
46
- * `Object#hash` is no longer used to calculate cache keys due to a potential risk of having hash collisions (solnic)
47
- * Predicate arguments are used again for template cache keys (solnic)
48
- * `I18n` messages backend no longer evaluates templates twice (solnic)
84
+ - `Object#hash` is no longer used to calculate cache keys due to a potential risk of having hash collisions (solnic)
85
+ - Predicate arguments are used again for template cache keys (solnic)
86
+ - `I18n` messages backend no longer evaluates templates twice (solnic)
49
87
 
50
88
  [Compare v1.0.2...v1.0.3](https://github.com/dry-rb/dry-schema/compare/v1.0.2...v1.0.3)
51
89
 
@@ -53,7 +91,7 @@
53
91
 
54
92
  ### Fixed
55
93
 
56
- * Caching message templates uses restricted set of known keys to calculate cache keys (issue #132) (solnic)
94
+ - Caching message templates uses restricted set of known keys to calculate cache keys (issue #132) (solnic)
57
95
 
58
96
  [Compare v1.0.1...v1.0.2](https://github.com/dry-rb/dry-schema/compare/v1.0.1...v1.0.2)
59
97
 
@@ -61,7 +99,7 @@
61
99
 
62
100
  ### Fixed
63
101
 
64
- * Applying `key?` predicate no longer causes recursive calls to `Result#errors` (issue #130) (solnic)
102
+ - Applying `key?` predicate no longer causes recursive calls to `Result#errors` (issue #130) (solnic)
65
103
 
66
104
  [Compare v1.0.0...v1.0.1](https://github.com/dry-rb/dry-schema/compare/v1.0.0...v1.0.1)
67
105
 
@@ -69,12 +107,12 @@
69
107
 
70
108
  ### Changed
71
109
 
72
- * [BREAKING] `Result#to_hash` was removed (solnic)
110
+ - [BREAKING] `Result#to_hash` was removed (solnic)
73
111
 
74
112
  ### Fixed
75
113
 
76
- * Setting `:any` as the type spec no longer crashes (solnic)
77
- * `Result#error?` handles paths to array elements correctly (solnic)
114
+ - Setting `:any` as the type spec no longer crashes (solnic)
115
+ - `Result#error?` handles paths to array elements correctly (solnic)
78
116
 
79
117
  [Compare v0.6.0...v1.0.0](https://github.com/dry-rb/dry-schema/compare/v0.6.0...v1.0.0)
80
118
 
@@ -82,9 +120,9 @@
82
120
 
83
121
  ### Changed
84
122
 
85
- * Dependency on `dry-types` was bumped to `~> 1.0` (solnic)
86
- * Dependency on `dry-logic` was bumped to `~> 1.0` (solnic)
87
- * Dependency on `dry-initializer` was bumped to `~> 3.0` (solnic)
123
+ - Dependency on `dry-types` was bumped to `~> 1.0` (solnic)
124
+ - Dependency on `dry-logic` was bumped to `~> 1.0` (solnic)
125
+ - Dependency on `dry-initializer` was bumped to `~> 3.0` (solnic)
88
126
 
89
127
  [Compare v0.5.1...v0.6.0](https://github.com/dry-rb/dry-schema/compare/v0.5.1...v0.6.0)
90
128
 
@@ -92,7 +130,7 @@
92
130
 
93
131
  ### Fixed
94
132
 
95
- * Key map no longer crashes on unexpected input (issue #118) (solnic)
133
+ - Key map no longer crashes on unexpected input (issue #118) (solnic)
96
134
 
97
135
  [Compare v0.5.0...v0.5.1](https://github.com/dry-rb/dry-schema/compare/v0.5.0...v0.5.1)
98
136
 
@@ -100,7 +138,7 @@
100
138
 
101
139
  ### Added
102
140
 
103
- * Support for arbitrary meta-data in messages, ie:
141
+ - Support for arbitrary meta-data in messages, ie:
104
142
 
105
143
  ```yaml
106
144
  en:
@@ -113,10 +151,10 @@
113
151
 
114
152
  Now your error hash will include `{ foo: [{ text: 'cannot be blank', code: 123 }] }` (solnic + flash-gordon)
115
153
 
116
- * Support for type specs in `array` macro, ie `required(:tags).array(:integer)` (solnic)
117
- * Support for type specs in `each` macro, ie `required(:tags).each(:integer)` (solnic)
118
- * Shortcut for defining an array with hash as its member, ie:
119
-
154
+ - Support for type specs in `array` macro, ie `required(:tags).array(:integer)` (solnic)
155
+ - Support for type specs in `each` macro, ie `required(:tags).each(:integer)` (solnic)
156
+ - Shortcut for defining an array with hash as its member, ie:
157
+
120
158
  ```ruby
121
159
  Dry::Schema.Params do
122
160
  required(:tags).array(:hash) do
@@ -127,13 +165,13 @@
127
165
 
128
166
  ### Fixed
129
167
 
130
- * Inferring predicates doesn't crash when `Any` type is used (flash-gordon)
131
- * Inferring type specs when type is already set works correctly (solnic)
168
+ - Inferring predicates doesn't crash when `Any` type is used (flash-gordon)
169
+ - Inferring type specs when type is already set works correctly (solnic)
132
170
 
133
171
  ### Changed
134
172
 
135
- * [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (flash-gordon)
136
- * When `:hints` are disabled, result AST will not include hint nodes (solnic)
173
+ - [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (flash-gordon)
174
+ - When `:hints` are disabled, result AST will not include hint nodes (solnic)
137
175
 
138
176
  [Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-schema/compare/v0.4.0...v0.5.0)
139
177
 
@@ -141,30 +179,30 @@
141
179
 
142
180
  ### Added
143
181
 
144
- * Schemas are now compatible with procs via `#to_proc` (issue #53) (solnic)
145
- * Support for configuring `top_namespace` for localized messages (solnic)
146
- * Support for configuring more than one load path for localized messages (solnic)
147
- * Support for inferring predicates from arbitrary types (issue #101) (solnic)
182
+ - Schemas are now compatible with procs via `#to_proc` (issue #53) (solnic)
183
+ - Support for configuring `top_namespace` for localized messages (solnic)
184
+ - Support for configuring more than one load path for localized messages (solnic)
185
+ - Support for inferring predicates from arbitrary types (issue #101) (solnic)
148
186
 
149
187
  ### Fixed
150
188
 
151
- * Handling of messages for `optional` keys without value rules works correctly (issue #87) (solnic)
152
- * Message structure for `optional` keys with an array of hashes no longer duplicates keys (issue #89) (solnic)
153
- * Inferring `:date_time?` predicate works correctly with `DateTime` types (issue #97) (solnic)
189
+ - Handling of messages for `optional` keys without value rules works correctly (issue #87) (solnic)
190
+ - Message structure for `optional` keys with an array of hashes no longer duplicates keys (issue #89) (solnic)
191
+ - Inferring `:date_time?` predicate works correctly with `DateTime` types (issue #97) (solnic)
154
192
 
155
193
  ### Changed
156
194
 
157
- * [BREAKING] Updated to work with `dry-types 0.15.0` (flash-gordon)
158
- * [BREAKING] `Result#{errors,messages,hints}` returns `MessageSet` object now which is an enumerable coercible to a hash (solnic)
159
- * [BREAKING] `Messages` backend classes no longer use global configuration (solnic)
160
- * [BREAKING] Passing a non-symbol key name in the DSL will raise `ArgumentError` (issue #29) (solnic)
161
- * [BREAKING] Configuration for message backends is now nested under `messages` key with following settings:
162
- * `messages.backend` - previously `messages`
163
- * `messages.load_paths` - previously `messages_path`
164
- * `messages.namespace` - previously `namespace`
165
- * `messages.top_namespace` - **new setting** see above
166
- * [BREAKING] `Messages::I18n` uses `I18.store_translations` instead of messing with `I18n.load_path` (solnic)
167
- * Schemas (`Params` and `JSON`) have nicer inspect (solnic)
195
+ - [BREAKING] Updated to work with `dry-types 0.15.0` (flash-gordon)
196
+ - [BREAKING] `Result#{errors,messages,hints}` returns `MessageSet` object now which is an enumerable coercible to a hash (solnic)
197
+ - [BREAKING] `Messages` backend classes no longer use global configuration (solnic)
198
+ - [BREAKING] Passing a non-symbol key name in the DSL will raise `ArgumentError` (issue #29) (solnic)
199
+ - [BREAKING] Configuration for message backends is now nested under `messages` key with following settings:
200
+ - `messages.backend` - previously `messages`
201
+ - `messages.load_paths` - previously `messages_path`
202
+ - `messages.namespace` - previously `namespace`
203
+ - `messages.top_namespace` - **new setting** see above
204
+ - [BREAKING] `Messages::I18n` uses `I18.store_translations` instead of messing with `I18n.load_path` (solnic)
205
+ - Schemas (`Params` and `JSON`) have nicer inspect (solnic)
168
206
 
169
207
  [Compare v0.3.0...v0.4.0](https://github.com/dry-rb/dry-schema/compare/v0.3.0...v0.4.0)
170
208
 
@@ -172,16 +210,16 @@
172
210
 
173
211
  ### Fixed
174
212
 
175
- * Configuration is properly inherited from a parent schema (skryukov)
176
- * `Result#error?` returns `true` when a preceding key has errors (solnic)
177
- * Predicate inferrer no longer chokes on sum, constructor and enum types (solnic)
178
- * Predicate inferrer infers `:bool?` from boolean types (solnic)
179
- * Block-based definitions using `array` works correctly (solnic)
180
- * Using a disjunction with `array` and `hash` produces correct errors when element validation for array failed (solnic)
213
+ - Configuration is properly inherited from a parent schema (skryukov)
214
+ - `Result#error?` returns `true` when a preceding key has errors (solnic)
215
+ - Predicate inferrer no longer chokes on sum, constructor and enum types (solnic)
216
+ - Predicate inferrer infers `:bool?` from boolean types (solnic)
217
+ - Block-based definitions using `array` works correctly (solnic)
218
+ - Using a disjunction with `array` and `hash` produces correct errors when element validation for array failed (solnic)
181
219
 
182
220
  ### Changed
183
221
 
184
- * Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (solnic)
222
+ - Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (solnic)
185
223
 
186
224
  [Compare v0.2.0...v0.3.0](https://github.com/dry-rb/dry-schema/compare/v0.2.0...v0.3.0)
187
225
 
@@ -189,28 +227,28 @@
189
227
 
190
228
  ### Added
191
229
 
192
- * New `hash` macro which prepends `hash?` type-check and allows nested schema definition (solnic)
193
- * New `array` macro which works like `each` but prepends `array?` type-check (solnic)
230
+ - New `hash` macro which prepends `hash?` type-check and allows nested schema definition (solnic)
231
+ - New `array` macro which works like `each` but prepends `array?` type-check (solnic)
194
232
 
195
233
  ### Fixed
196
234
 
197
- * Rule name translation works correctly with I18n (issue #52) (solnic)
198
- * Rule name translation works correctly with namespaced messages (both I18n and plain YAML) (issue #57) (solnic)
199
- * Error messages under namespaces are correctly resolved for overridden names (issue #53) (solnic)
200
- * Namespaced error messages work correctly when schemas are reused within other schemas (issue #49) (solnic)
201
- * Child schema can override inherited rules now (issue #66) (skryukov)
202
- * Hints are correctly generated for disjunction that use type-check predicates (issue #24) (solnic)
203
- * Hints are correctly generated for nested schemas (issue #26) (solnic)
204
- * `filled` macro respects inferred type-check predicates and puts them in front (solnic)
205
- * Value coercion works correctly with re-usable nested schemas (issue #25) (solnic)
235
+ - Rule name translation works correctly with I18n (issue #52) (solnic)
236
+ - Rule name translation works correctly with namespaced messages (both I18n and plain YAML) (issue #57) (solnic)
237
+ - Error messages under namespaces are correctly resolved for overridden names (issue #53) (solnic)
238
+ - Namespaced error messages work correctly when schemas are reused within other schemas (issue #49) (solnic)
239
+ - Child schema can override inherited rules now (issue #66) (skryukov)
240
+ - Hints are correctly generated for disjunction that use type-check predicates (issue #24) (solnic)
241
+ - Hints are correctly generated for nested schemas (issue #26) (solnic)
242
+ - `filled` macro respects inferred type-check predicates and puts them in front (solnic)
243
+ - Value coercion works correctly with re-usable nested schemas (issue #25) (solnic)
206
244
 
207
245
  ### Changed
208
246
 
209
- * [BREAKING] **Messages are now configured under `dry_schema` namespace by default** (issue #38) (solnic)
210
- * [BREAKING] Hints are now an optional feature provided by `:hints` extension, to load it do `Dry::Schema.load_extensions(:hints)` (solnic)
211
- * [BREAKING] Hints generation was improved in general, output of `Result#messages` and `Result#hints` changed in some cases (solnic)
212
- * [BREAKING] `schema` macro no longer prepends `hash?` check, for this behavior use the new `hash` macro (see #31) (solnic)
213
- * [BREAKING] Support for MRI < 2.4 was dropped (solnic)
247
+ - [BREAKING] **Messages are now configured under `dry_schema` namespace by default** (issue #38) (solnic)
248
+ - [BREAKING] Hints are now an optional feature provided by `:hints` extension, to load it do `Dry::Schema.load_extensions(:hints)` (solnic)
249
+ - [BREAKING] Hints generation was improved in general, output of `Result#messages` and `Result#hints` changed in some cases (solnic)
250
+ - [BREAKING] `schema` macro no longer prepends `hash?` check, for this behavior use the new `hash` macro (see #31) (solnic)
251
+ - [BREAKING] Support for MRI < 2.4 was dropped (solnic)
214
252
 
215
253
  [Compare v0.1.1...v0.2.0](https://github.com/dry-rb/dry-schema/compare/v0.1.1...v0.2.0)
216
254
 
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [gem]: https://rubygems.org/gems/dry-schema
2
- [travis]: https://travis-ci.org/dry-rb/dry-schema
2
+ [travis]: https://travis-ci.com/dry-rb/dry-schema
3
3
  [codeclimate]: https://codeclimate.com/github/dry-rb/dry-schema
4
4
  [chat]: https://dry-rb.zulipchat.com
5
5
  [inchpages]: http://inch-ci.org/github/dry-rb/dry-schema
@@ -7,7 +7,7 @@
7
7
  # dry-schema [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
8
 
9
9
  [![Gem Version](https://badge.fury.io/rb/dry-schema.svg)][gem]
10
- [![Build Status](https://travis-ci.org/dry-rb/dry-schema.svg?branch=master)][travis]
10
+ [![Build Status](https://travis-ci.com/dry-rb/dry-schema.svg?branch=master)][travis]
11
11
  [![Code Climate](https://codeclimate.com/github/dry-rb/dry-schema/badges/gpa.svg)][codeclimate]
12
12
  [![Test Coverage](https://codeclimate.com/github/dry-rb/dry-schema/badges/coverage.svg)][codeclimate]
13
13
  [![Inline docs](http://inch-ci.org/github/dry-rb/dry-schema.svg?branch=master)][inchpages]
@@ -231,7 +231,7 @@ module Dry
231
231
  #
232
232
  # @api private
233
233
  def new(options = EMPTY_HASH, &block)
234
- self.class.new(options.merge(processor_type: processor_type), &block)
234
+ self.class.new(options.merge(processor_type: processor_type, config: config), &block)
235
235
  end
236
236
 
237
237
  # Set a type for the given key name
@@ -200,13 +200,7 @@ module Dry
200
200
 
201
201
  type_predicates = predicate_inferrer[resolved_type]
202
202
 
203
- unless type_predicates.empty? || predicates.include?(type_predicates)
204
- if type_predicates.is_a?(::Array) && type_predicates.size.equal?(1)
205
- predicates.unshift(type_predicates[0])
206
- else
207
- predicates.unshift(type_predicates)
208
- end
209
- end
203
+ predicates.replace(type_predicates + predicates) unless type_predicates.empty?
210
204
 
211
205
  return self if predicates.empty?
212
206
  end
@@ -11,10 +11,10 @@ module Dry
11
11
  class Schema < Value
12
12
  # @api private
13
13
  def call(*args, &block)
14
- super(*args) unless args.empty?
14
+ super(*args, &nil) unless args.empty?
15
15
 
16
16
  if block
17
- schema = define(&block)
17
+ schema = define(*args, &block)
18
18
  trace << schema.to_rule
19
19
  end
20
20
 
@@ -24,11 +24,17 @@ module Dry
24
24
  private
25
25
 
26
26
  # @api private
27
- def define(&block)
27
+ def define(*args, &block)
28
28
  definition = schema_dsl.new(&block)
29
29
  schema = definition.call
30
-
31
- type_schema = array? ? parent_type.of(definition.type_schema) : definition.type_schema
30
+ type_schema =
31
+ if array?
32
+ parent_type.of(definition.type_schema)
33
+ elsif redefined_schema?(args)
34
+ parent_type.schema(definition.types)
35
+ else
36
+ definition.type_schema
37
+ end
32
38
  final_type = optional? ? type_schema.optional : type_schema
33
39
 
34
40
  type(final_type)
@@ -54,6 +60,16 @@ module Dry
54
60
  def array?
55
61
  parent_type.respond_to?(:of)
56
62
  end
63
+
64
+ # @api private
65
+ def schema?
66
+ parent_type.respond_to?(:schema)
67
+ end
68
+
69
+ # @api private
70
+ def redefined_schema?(args)
71
+ schema? && args.first.is_a?(Processor)
72
+ end
57
73
  end
58
74
  end
59
75
  end
@@ -22,9 +22,15 @@ module Dry
22
22
  }.freeze
23
23
 
24
24
  REDUCED_TYPES = {
25
- %i[true? false?] => :bool?
25
+ [[[:true?], [:false?]]] => %i[bool?]
26
26
  }.freeze
27
27
 
28
+ HASH = %i[hash?].freeze
29
+
30
+ ARRAY = %i[array?].freeze
31
+
32
+ NIL = %i[nil?].freeze
33
+
28
34
  # Compiler reduces type AST into a list of predicates
29
35
  #
30
36
  # @api private
@@ -40,7 +46,7 @@ module Dry
40
46
 
41
47
  # @api private
42
48
  def infer_predicate(type)
43
- TYPE_TO_PREDICATE.fetch(type) { :"#{type.name.split('::').last.downcase}?" }
49
+ [TYPE_TO_PREDICATE.fetch(type) { :"#{type.name.split('::').last.downcase}?" }]
44
50
  end
45
51
 
46
52
  # @api private
@@ -54,21 +60,21 @@ module Dry
54
60
  type = node[0]
55
61
  predicate = infer_predicate(type)
56
62
 
57
- if registry.key?(predicate)
63
+ if registry.key?(predicate[0])
58
64
  predicate
59
65
  else
60
- { type?: type }
66
+ [type?: type]
61
67
  end
62
68
  end
63
69
 
64
70
  # @api private
65
71
  def visit_hash(_)
66
- :hash?
72
+ HASH
67
73
  end
68
74
 
69
75
  # @api private
70
76
  def visit_array(_)
71
- :array?
77
+ ARRAY
72
78
  end
73
79
 
74
80
  # @api private
@@ -90,26 +96,73 @@ module Dry
90
96
 
91
97
  # @api private
92
98
  def visit_sum(node)
93
- left, right = node
99
+ left_node, right_node, = node
100
+ left = visit(left_node)
101
+ right = visit(right_node)
94
102
 
95
- predicates = [visit(left), visit(right)]
96
-
97
- if predicates.first == :nil?
98
- predicates[1..predicates.size - 1]
103
+ if left.eql?(NIL)
104
+ right
99
105
  else
100
- predicates
106
+ [[left, right]]
101
107
  end
102
108
  end
103
109
 
104
110
  # @api private
105
111
  def visit_constrained(node)
106
- other, * = node
107
- visit(other)
112
+ other, rules = node
113
+ predicates = visit(rules)
114
+
115
+ if predicates.empty?
116
+ visit(other)
117
+ else
118
+ [*visit(other), *merge_predicates(predicates)]
119
+ end
108
120
  end
109
121
 
110
122
  # @api private
111
123
  def visit_any(_)
112
- nil
124
+ EMPTY_ARRAY
125
+ end
126
+
127
+ # @api private
128
+ def visit_and(node)
129
+ left, right = node
130
+ visit(left) + visit(right)
131
+ end
132
+
133
+ # @api private
134
+ def visit_predicate(node)
135
+ pred, args = node
136
+
137
+ if pred.equal?(:type?)
138
+ EMPTY_ARRAY
139
+ elsif registry.key?(pred)
140
+ *curried, _ = args
141
+ values = curried.map { |_, v| v }
142
+
143
+ if values.empty?
144
+ [pred]
145
+ else
146
+ [pred => values[0]]
147
+ end
148
+ else
149
+ EMPTY_ARRAY
150
+ end
151
+ end
152
+
153
+ private
154
+
155
+ # @api private
156
+ def merge_predicates(nodes)
157
+ preds, merged = nodes.each_with_object([[], {}]) do |predicate, (ps, h)|
158
+ if predicate.is_a?(::Hash)
159
+ h.update(predicate)
160
+ else
161
+ ps << predicate
162
+ end
163
+ end
164
+
165
+ merged.empty? ? preds : [*preds, merged]
113
166
  end
114
167
  end
115
168
 
@@ -134,7 +187,7 @@ module Dry
134
187
  if predicates.is_a?(Hash)
135
188
  predicates
136
189
  else
137
- Array(REDUCED_TYPES[predicates] || predicates).flatten
190
+ REDUCED_TYPES[predicates] || predicates
138
191
  end
139
192
  end
140
193
  end
@@ -29,33 +29,28 @@ module Dry
29
29
  end
30
30
 
31
31
  # @api private
32
- def evaluate(*predicates, **opts)
33
- pred_opts = opts.dup
34
- pred_opts.delete(:type_spec)
35
-
36
- predicates.each do |predicate|
37
- if predicate.respond_to?(:call)
38
- append(predicate)
39
- elsif predicate.is_a?(::Hash)
40
- evaluate_hash_predicates(predicate)
41
- elsif predicate.is_a?(::Array)
42
- append(predicate.map { |pred| __send__(pred) }.reduce(:|))
43
- else
44
- append(__send__(predicate))
45
- end
32
+ def evaluate(*args, type_spec: ::Dry::Schema::Undefined, **opts)
33
+ predicates = opts.empty? ? args : args.push(opts)
34
+ evaluate_predicates(predicates).each do |rule|
35
+ append(rule)
46
36
  end
47
37
 
48
- evaluate_hash_predicates(pred_opts)
49
-
50
38
  self
51
39
  end
52
40
 
53
41
  # @api private
54
- def evaluate_hash_predicates(predicates)
55
- predicates.each do |predicate, *args|
56
- append(__send__(predicate, *args))
42
+ def evaluate_predicates(predicates)
43
+ predicates.flat_map do |predicate|
44
+ if predicate.respond_to?(:call)
45
+ predicate
46
+ elsif predicate.is_a?(::Array)
47
+ predicate.map { |pred| evaluate_predicates(pred).reduce(:&) }.reduce(:|)
48
+ elsif predicate.is_a?(::Hash)
49
+ predicate.map { |pred, *args| __send__(pred, *args) }
50
+ else
51
+ __send__(predicate)
52
+ end
57
53
  end
58
- self
59
54
  end
60
55
 
61
56
  # @api private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Schema
5
- VERSION = '1.2.0'
5
+ VERSION = '1.3.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.2.0
4
+ version: 1.3.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-06-13 00:00:00.000000000 Z
11
+ date: 2019-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby