dry-schema 1.2.0 → 1.3.1

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: 7a41a84d107f4694b4009a58065e603b2489e87b55c91fba3884b2af2562d3ef
4
+ data.tar.gz: fce0be0f38499c070f1fd1dc55c3c3407decef76aba778b3a27a839440bd888f
5
5
  SHA512:
6
- metadata.gz: b1317319cec5bacf68ec380166226382c4d10818db4b1a575841f04c43b12b2b420877121876ebb13ce85c59b7b88a375c1f9798523cc6fb123e274507203cd2
7
- data.tar.gz: fa995747a3efd66855e6d8cbb7d07e6d2002cd9e459237acc58b8747dd7f7d728d4a5f57482269d25e3c63319110975e8b01ec713536defd31742812dc92e334
6
+ metadata.gz: 3fb5a9045111eadb411f2afc39819dba78651a9170968b212eaebfd613376f7a22db40660e90b3ac6d264177a1e8d1ead05736f8ed2b13a5d3bdaf1e382f2c44
7
+ data.tar.gz: c995cfb2e5e4c5f90d6109cbd01a81e627027ac730034422a3d1fbb791ab248bc9572d59fef5ff7c54cb69baeaeb6d8e21914e5641ba81f560e3cff4fc31673d
@@ -1,22 +1,69 @@
1
+ # 1.3.1 2019-07-08
2
+
3
+ ### Fixed
4
+
5
+ * `Result#error?` works correctly with nested hashes and arrays (@solnic)
6
+ * `:hints` extension no longer causes a crash where base messages are generated too (issue #165) (@solnic)
7
+
8
+ [Compare v1.3.0...v1.3.1](https://github.com/dry-rb/dry-schema/compare/v1.3.0...v1.3.1)
9
+
10
+ # 1.3.0 2019-07-06
11
+
12
+ ### Added
13
+
14
+ - Automatic predicate inferring for constrained types! (@flash-gordon)
15
+
16
+ ```ruby
17
+ Types::Name = Types::String.constrained(min_size: 1)
18
+
19
+ schema = Dry::Schema.define do
20
+ required(:name).value(Types::Name)
21
+ end
22
+
23
+ schema.(name: '').errors.to_h # => { name: ["size cannot be less than 1"] }
24
+ ```
25
+
26
+ - Support for redefining re-used schemas (issue #43) (@skryukov)
27
+
28
+ ### Fixed
29
+
30
+ - Type container is passed down to nested schemas (@flash-gordon)
31
+
32
+ [Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-schema/compare/v1.2.0...v1.3.0)
33
+
1
34
  # v1.2.0 2019-06-13
2
35
 
3
36
  ### Added
4
37
 
5
- * Ability to configure your own type container (@Morozzzko)
38
+ - Ability to configure your own type container (@Morozzzko)
39
+
40
+ ```ruby
41
+ types = Dry::Schema::TypeContainer.new
42
+ types.register(
43
+ 'params.trimmed_string',
44
+ Types::String.constructor(&:strip).constructor(&:downcase)
45
+ )
46
+
47
+ Dry::Schema.Params do
48
+ config.types = types
49
+
50
+ require(:name).value(:trimmed_string)
51
+ end
52
+ ```
6
53
 
7
54
  ### Fixed
8
55
 
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)
56
+ - `filled` macro no longer generates incorrect messages for arrays (issue #151) (@solnic)
57
+ - `filled` macro works correctly with constructor types (@solnic)
58
+ - `filled` works correctly with nested schemas (#149) (@solnic + @timriley)
59
+ - Custom array constructors are no longer discredited by `array` macro (@solnic)
60
+ - `BigDecimal` type is correctly handled by predicate inference (@solnic)
61
+ - Works with latest `dry-logic` which provides the new `respond_to?` predicate (#153) (@flash-gordon)
15
62
 
16
63
  ### Changed
17
64
 
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)
65
+ - Fixes related to `filled` restored pre-1.1.0 behavior of `:hints` which are again included (@solnic)
66
+ - `filled` no longer uses filter rules to handle empty strings in `Params` (@solnic)
20
67
 
21
68
  [Compare v1.1.0...v1.2.0](https://github.com/dry-rb/dry-schema/compare/v1.1.0...v1.2.0)
22
69
 
@@ -24,18 +71,18 @@
24
71
 
25
72
  ### Added
26
73
 
27
- * `config.messages.default_locale` for setting...default locale (surprise, surprise) (solnic)
28
- * `Config` exposes `predicates` setting too (solnic)
74
+ - `config.messages.default_locale` for setting...default locale (surprise, surprise) (solnic)
75
+ - `Config` exposes `predicates` setting too (solnic)
29
76
 
30
77
  ### Fixed
31
78
 
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)
79
+ - `filled` macro behavior results in `must be filled` error messages when appropriate - see PR #141 for more information (issue #134) (solnic)
80
+ - Filter rules no longer cause keys to be added to input (issue #142) (solnic)
81
+ - Filter rules work now with inheritance (solnic)
82
+ - Inherited type schemas used by coercion are now properly configured as `lax` type (solnic)
83
+ - `Config` is now finalized before instantiating schemas and properly dupped when its inherited (flash-gordon + solnic)
84
+ - `Config#eql?` works as expected (solnic)
85
+ - Predicates are properly inferred from array with a member type spec, ie `array[:integer]` results in `array? + each(:integer?)` (issue #140) (solnic)
39
86
 
40
87
  [Compare v1.0.3...v1.1.0](https://github.com/dry-rb/dry-schema/compare/v1.0.3...v1.1.0)
41
88
 
@@ -43,9 +90,9 @@
43
90
 
44
91
  ### Fixed
45
92
 
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)
93
+ - `Object#hash` is no longer used to calculate cache keys due to a potential risk of having hash collisions (solnic)
94
+ - Predicate arguments are used again for template cache keys (solnic)
95
+ - `I18n` messages backend no longer evaluates templates twice (solnic)
49
96
 
50
97
  [Compare v1.0.2...v1.0.3](https://github.com/dry-rb/dry-schema/compare/v1.0.2...v1.0.3)
51
98
 
@@ -53,7 +100,7 @@
53
100
 
54
101
  ### Fixed
55
102
 
56
- * Caching message templates uses restricted set of known keys to calculate cache keys (issue #132) (solnic)
103
+ - Caching message templates uses restricted set of known keys to calculate cache keys (issue #132) (solnic)
57
104
 
58
105
  [Compare v1.0.1...v1.0.2](https://github.com/dry-rb/dry-schema/compare/v1.0.1...v1.0.2)
59
106
 
@@ -61,7 +108,7 @@
61
108
 
62
109
  ### Fixed
63
110
 
64
- * Applying `key?` predicate no longer causes recursive calls to `Result#errors` (issue #130) (solnic)
111
+ - Applying `key?` predicate no longer causes recursive calls to `Result#errors` (issue #130) (solnic)
65
112
 
66
113
  [Compare v1.0.0...v1.0.1](https://github.com/dry-rb/dry-schema/compare/v1.0.0...v1.0.1)
67
114
 
@@ -69,12 +116,12 @@
69
116
 
70
117
  ### Changed
71
118
 
72
- * [BREAKING] `Result#to_hash` was removed (solnic)
119
+ - [BREAKING] `Result#to_hash` was removed (solnic)
73
120
 
74
121
  ### Fixed
75
122
 
76
- * Setting `:any` as the type spec no longer crashes (solnic)
77
- * `Result#error?` handles paths to array elements correctly (solnic)
123
+ - Setting `:any` as the type spec no longer crashes (solnic)
124
+ - `Result#error?` handles paths to array elements correctly (solnic)
78
125
 
79
126
  [Compare v0.6.0...v1.0.0](https://github.com/dry-rb/dry-schema/compare/v0.6.0...v1.0.0)
80
127
 
@@ -82,9 +129,9 @@
82
129
 
83
130
  ### Changed
84
131
 
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)
132
+ - Dependency on `dry-types` was bumped to `~> 1.0` (solnic)
133
+ - Dependency on `dry-logic` was bumped to `~> 1.0` (solnic)
134
+ - Dependency on `dry-initializer` was bumped to `~> 3.0` (solnic)
88
135
 
89
136
  [Compare v0.5.1...v0.6.0](https://github.com/dry-rb/dry-schema/compare/v0.5.1...v0.6.0)
90
137
 
@@ -92,7 +139,7 @@
92
139
 
93
140
  ### Fixed
94
141
 
95
- * Key map no longer crashes on unexpected input (issue #118) (solnic)
142
+ - Key map no longer crashes on unexpected input (issue #118) (solnic)
96
143
 
97
144
  [Compare v0.5.0...v0.5.1](https://github.com/dry-rb/dry-schema/compare/v0.5.0...v0.5.1)
98
145
 
@@ -100,7 +147,7 @@
100
147
 
101
148
  ### Added
102
149
 
103
- * Support for arbitrary meta-data in messages, ie:
150
+ - Support for arbitrary meta-data in messages, ie:
104
151
 
105
152
  ```yaml
106
153
  en:
@@ -113,10 +160,10 @@
113
160
 
114
161
  Now your error hash will include `{ foo: [{ text: 'cannot be blank', code: 123 }] }` (solnic + flash-gordon)
115
162
 
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
-
163
+ - Support for type specs in `array` macro, ie `required(:tags).array(:integer)` (solnic)
164
+ - Support for type specs in `each` macro, ie `required(:tags).each(:integer)` (solnic)
165
+ - Shortcut for defining an array with hash as its member, ie:
166
+
120
167
  ```ruby
121
168
  Dry::Schema.Params do
122
169
  required(:tags).array(:hash) do
@@ -127,13 +174,13 @@
127
174
 
128
175
  ### Fixed
129
176
 
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)
177
+ - Inferring predicates doesn't crash when `Any` type is used (flash-gordon)
178
+ - Inferring type specs when type is already set works correctly (solnic)
132
179
 
133
180
  ### Changed
134
181
 
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)
182
+ - [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (flash-gordon)
183
+ - When `:hints` are disabled, result AST will not include hint nodes (solnic)
137
184
 
138
185
  [Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-schema/compare/v0.4.0...v0.5.0)
139
186
 
@@ -141,30 +188,30 @@
141
188
 
142
189
  ### Added
143
190
 
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)
191
+ - Schemas are now compatible with procs via `#to_proc` (issue #53) (solnic)
192
+ - Support for configuring `top_namespace` for localized messages (solnic)
193
+ - Support for configuring more than one load path for localized messages (solnic)
194
+ - Support for inferring predicates from arbitrary types (issue #101) (solnic)
148
195
 
149
196
  ### Fixed
150
197
 
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)
198
+ - Handling of messages for `optional` keys without value rules works correctly (issue #87) (solnic)
199
+ - Message structure for `optional` keys with an array of hashes no longer duplicates keys (issue #89) (solnic)
200
+ - Inferring `:date_time?` predicate works correctly with `DateTime` types (issue #97) (solnic)
154
201
 
155
202
  ### Changed
156
203
 
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)
204
+ - [BREAKING] Updated to work with `dry-types 0.15.0` (flash-gordon)
205
+ - [BREAKING] `Result#{errors,messages,hints}` returns `MessageSet` object now which is an enumerable coercible to a hash (solnic)
206
+ - [BREAKING] `Messages` backend classes no longer use global configuration (solnic)
207
+ - [BREAKING] Passing a non-symbol key name in the DSL will raise `ArgumentError` (issue #29) (solnic)
208
+ - [BREAKING] Configuration for message backends is now nested under `messages` key with following settings:
209
+ - `messages.backend` - previously `messages`
210
+ - `messages.load_paths` - previously `messages_path`
211
+ - `messages.namespace` - previously `namespace`
212
+ - `messages.top_namespace` - **new setting** see above
213
+ - [BREAKING] `Messages::I18n` uses `I18.store_translations` instead of messing with `I18n.load_path` (solnic)
214
+ - Schemas (`Params` and `JSON`) have nicer inspect (solnic)
168
215
 
169
216
  [Compare v0.3.0...v0.4.0](https://github.com/dry-rb/dry-schema/compare/v0.3.0...v0.4.0)
170
217
 
@@ -172,16 +219,16 @@
172
219
 
173
220
  ### Fixed
174
221
 
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)
222
+ - Configuration is properly inherited from a parent schema (skryukov)
223
+ - `Result#error?` returns `true` when a preceding key has errors (solnic)
224
+ - Predicate inferrer no longer chokes on sum, constructor and enum types (solnic)
225
+ - Predicate inferrer infers `:bool?` from boolean types (solnic)
226
+ - Block-based definitions using `array` works correctly (solnic)
227
+ - Using a disjunction with `array` and `hash` produces correct errors when element validation for array failed (solnic)
181
228
 
182
229
  ### Changed
183
230
 
184
- * Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (solnic)
231
+ - Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (solnic)
185
232
 
186
233
  [Compare v0.2.0...v0.3.0](https://github.com/dry-rb/dry-schema/compare/v0.2.0...v0.3.0)
187
234
 
@@ -189,28 +236,28 @@
189
236
 
190
237
  ### Added
191
238
 
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)
239
+ - New `hash` macro which prepends `hash?` type-check and allows nested schema definition (solnic)
240
+ - New `array` macro which works like `each` but prepends `array?` type-check (solnic)
194
241
 
195
242
  ### Fixed
196
243
 
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)
244
+ - Rule name translation works correctly with I18n (issue #52) (solnic)
245
+ - Rule name translation works correctly with namespaced messages (both I18n and plain YAML) (issue #57) (solnic)
246
+ - Error messages under namespaces are correctly resolved for overridden names (issue #53) (solnic)
247
+ - Namespaced error messages work correctly when schemas are reused within other schemas (issue #49) (solnic)
248
+ - Child schema can override inherited rules now (issue #66) (skryukov)
249
+ - Hints are correctly generated for disjunction that use type-check predicates (issue #24) (solnic)
250
+ - Hints are correctly generated for nested schemas (issue #26) (solnic)
251
+ - `filled` macro respects inferred type-check predicates and puts them in front (solnic)
252
+ - Value coercion works correctly with re-usable nested schemas (issue #25) (solnic)
206
253
 
207
254
  ### Changed
208
255
 
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)
256
+ - [BREAKING] **Messages are now configured under `dry_schema` namespace by default** (issue #38) (solnic)
257
+ - [BREAKING] Hints are now an optional feature provided by `:hints` extension, to load it do `Dry::Schema.load_extensions(:hints)` (solnic)
258
+ - [BREAKING] Hints generation was improved in general, output of `Result#messages` and `Result#hints` changed in some cases (solnic)
259
+ - [BREAKING] `schema` macro no longer prepends `hash?` check, for this behavior use the new `hash` macro (see #31) (solnic)
260
+ - [BREAKING] Support for MRI < 2.4 was dropped (solnic)
214
261
 
215
262
  [Compare v0.1.1...v0.2.0](https://github.com/dry-rb/dry-schema/compare/v0.1.1...v0.2.0)
216
263
 
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
@@ -12,7 +12,7 @@ module Dry
12
12
  #
13
13
  # @return [Array<Message::Hint>]
14
14
  attr_reader :hints
15
-
15
+
16
16
  # Configuration option to enable/disable showing errors
17
17
  #
18
18
  # @return [Boolean]
@@ -37,6 +37,53 @@ module Dry
37
37
  @to_h ||= failures ? messages_map : messages_map(hints)
38
38
  end
39
39
  alias_method :to_hash, :to_h
40
+
41
+ private
42
+
43
+ # @api private
44
+ def unique_paths
45
+ messages.uniq(&:path).map(&:path)
46
+ end
47
+
48
+ # @api private
49
+ def messages_map(messages = self.messages)
50
+ return EMPTY_HASH if empty?
51
+
52
+ messages.reduce(placeholders) { |hash, msg|
53
+ node = msg.path.reduce(hash) { |a, e| a.is_a?(Hash) ? a[e] : a.last[e] }
54
+ (node[0].is_a?(::Array) ? node[0] : node) << msg.dump
55
+ hash
56
+ }
57
+ end
58
+
59
+ # @api private
60
+ #
61
+ # rubocop:disable Metrics/AbcSize
62
+ # rubocop:disable Metrics/PerceivedComplexity
63
+ def initialize_placeholders!
64
+ @placeholders = unique_paths.each_with_object(EMPTY_HASH.dup) { |path, hash|
65
+ curr_idx = 0
66
+ last_idx = path.size - 1
67
+ node = hash
68
+
69
+ while curr_idx <= last_idx
70
+ key = path[curr_idx]
71
+
72
+ next_node =
73
+ if node.is_a?(Array) && key.is_a?(Symbol)
74
+ node_hash = (node << [] << {}).last
75
+ node_hash[key] || (node_hash[key] = curr_idx < last_idx ? {} : [])
76
+ else
77
+ node[key] || (node[key] = curr_idx < last_idx ? {} : [])
78
+ end
79
+
80
+ node = next_node
81
+ curr_idx += 1
82
+ end
83
+ }
84
+ end
85
+ # rubocop:enable Metrics/AbcSize
86
+ # rubocop:enable Metrics/PerceivedComplexity
40
87
  end
41
88
  end
42
89
  end
@@ -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
@@ -60,7 +60,7 @@ module Dry
60
60
  #
61
61
  # If a string is passed, it will be compared with the text
62
62
  #
63
- # @param [Message,String]
63
+ # @param other [Message,String]
64
64
  #
65
65
  # @return [Boolean]
66
66
  #
@@ -65,8 +65,10 @@ module Dry
65
65
  # @api private
66
66
  def include?(other)
67
67
  return false unless same_root?(other)
68
- return false if index? && other.index? && !last.equal?(other.last)
69
- self >= other
68
+ return last.equal?(other.last) if index? && other.index?
69
+ return self.class.new([*to_a[0..-2]]).include?(other) if index?
70
+
71
+ self >= other && !other.key_matches(self).include?(nil)
70
72
  end
71
73
 
72
74
  # @api private
@@ -75,14 +77,16 @@ module Dry
75
77
 
76
78
  return 0 if keys.eql?(other.keys)
77
79
 
78
- res =
79
- map { |key| (idx = other.index(key)) && keys[idx].equal?(key) }
80
- .compact
81
- .reject { |value| value.equal?(false) }
80
+ res = key_matches(other).compact.reject { |value| value.equal?(false) }
82
81
 
83
82
  res.size < count ? 1 : -1
84
83
  end
85
84
 
85
+ # @api private
86
+ def key_matches(other)
87
+ map { |key| (idx = other.index(key)) && keys[idx].equal?(key) }
88
+ end
89
+
86
90
  # @api private
87
91
  def last
88
92
  keys.last
@@ -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.1'
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.1
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-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby