dry-schema 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/LICENSE +1 -1
- data/README.md +11 -2
- data/lib/dry-schema.rb +2 -0
- data/lib/dry/schema.rb +2 -0
- data/lib/dry/schema/compiler.rb +2 -0
- data/lib/dry/schema/config.rb +2 -0
- data/lib/dry/schema/constants.rb +4 -2
- data/lib/dry/schema/dsl.rb +5 -3
- data/lib/dry/schema/extensions.rb +2 -0
- data/lib/dry/schema/extensions/hints.rb +2 -0
- data/lib/dry/schema/extensions/hints/message_compiler_methods.rb +10 -3
- data/lib/dry/schema/extensions/hints/message_set_methods.rb +3 -1
- data/lib/dry/schema/extensions/hints/result_methods.rb +2 -0
- data/lib/dry/schema/extensions/monads.rb +3 -2
- data/lib/dry/schema/json.rb +3 -1
- data/lib/dry/schema/key.rb +3 -1
- data/lib/dry/schema/key_coercer.rb +2 -0
- data/lib/dry/schema/key_map.rb +3 -1
- data/lib/dry/schema/macros.rb +3 -0
- data/lib/dry/schema/macros/array.rb +27 -0
- data/lib/dry/schema/macros/core.rb +2 -0
- data/lib/dry/schema/macros/dsl.rb +3 -2
- data/lib/dry/schema/macros/each.rb +2 -0
- data/lib/dry/schema/macros/filled.rb +4 -2
- data/lib/dry/schema/macros/hash.rb +2 -0
- data/lib/dry/schema/macros/key.rb +7 -3
- data/lib/dry/schema/macros/maybe.rb +4 -2
- data/lib/dry/schema/macros/optional.rb +2 -0
- data/lib/dry/schema/macros/required.rb +2 -0
- data/lib/dry/schema/macros/schema.rb +2 -0
- data/lib/dry/schema/macros/value.rb +10 -3
- data/lib/dry/schema/message.rb +14 -0
- data/lib/dry/schema/message_compiler.rb +4 -2
- data/lib/dry/schema/message_compiler/visitor_opts.rb +2 -0
- data/lib/dry/schema/message_set.rb +2 -0
- data/lib/dry/schema/messages.rb +2 -0
- data/lib/dry/schema/messages/abstract.rb +5 -3
- data/lib/dry/schema/messages/i18n.rb +3 -1
- data/lib/dry/schema/messages/namespaced.rb +3 -1
- data/lib/dry/schema/messages/template.rb +3 -1
- data/lib/dry/schema/messages/yaml.rb +7 -3
- data/lib/dry/schema/namespaced_rule.rb +2 -0
- data/lib/dry/schema/params.rb +3 -1
- data/lib/dry/schema/path.rb +21 -2
- data/lib/dry/schema/predicate.rb +2 -0
- data/lib/dry/schema/predicate_inferrer.rb +69 -20
- data/lib/dry/schema/predicate_registry.rb +2 -0
- data/lib/dry/schema/processor.rb +11 -0
- data/lib/dry/schema/result.rb +3 -1
- data/lib/dry/schema/rule_applier.rb +2 -0
- data/lib/dry/schema/trace.rb +2 -0
- data/lib/dry/schema/type_registry.rb +3 -1
- data/lib/dry/schema/types.rb +2 -0
- data/lib/dry/schema/value_coercer.rb +2 -0
- data/lib/dry/schema/version.rb +3 -1
- metadata +24 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 149b82a73e8cd4d31c55fe1cf2bee1a7ebfb2afd696677522293da435f0224b1
|
4
|
+
data.tar.gz: ca76ca603a34906e61cfbd075e9667c97ee191591520e89b8a5d2e949c124426
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b94f326035f884457e2b6ce84ed427d2ec31011529cb8c4a987ff8c26a1bf4b66581ccd1e14ebe91cd4a0efbd05c9c04be6c47cfe959fa0f08687515f02d364
|
7
|
+
data.tar.gz: 356ae43e85fc3afdc0e8abd2628c06315ce5ed97d3ec74c40a3a32dd73b1300851c0f1f8c674abb73d3d8723292dfe0bf370ec5f5fcf1fd7f21fc5a8eb16633c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
# 0.3.0 2018-03-04
|
2
|
+
|
3
|
+
### Fixed
|
4
|
+
|
5
|
+
* Configuration is properly inherited from a parent schema (skryukov)
|
6
|
+
* `Result#error?` returns `true` when a preceding key has errors (solnic)
|
7
|
+
* Predicate inferrer no longer chokes on sum, constructor and enum types (solnic)
|
8
|
+
* Predicate inferrer infers `:bool?` from boolean types (solnic)
|
9
|
+
* Block-based definitions using `array` works correctly (solnic)
|
10
|
+
* Using a disjunction with `array` and `hash` produces correct errors when element validation for array failed (solnic)
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
* Required ruby version was removed from gemspec for people who are stuck on MRI 2.3.x (solnic)
|
15
|
+
|
16
|
+
[Compare v0.2.0...v0.3.0](https://github.com/dry-rb/dry-schema/compare/v0.2.0...v0.3.0)
|
17
|
+
|
1
18
|
# 0.2.0 2019-02-26
|
2
19
|
|
3
20
|
### Added
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -12,9 +12,18 @@
|
|
12
12
|
[][codeclimate]
|
13
13
|
[][inchpages]
|
14
14
|
|
15
|
-
|
15
|
+
## Links
|
16
16
|
|
17
|
-
* [Documentation](http://dry-rb.org/gems/dry-schema)
|
17
|
+
* [Documentation](http://dry-rb.org/gems/dry-schema)
|
18
|
+
|
19
|
+
## Supported Ruby versions
|
20
|
+
|
21
|
+
This library officially supports following Ruby versions:
|
22
|
+
|
23
|
+
* MRI >= `2.4`
|
24
|
+
* jruby >= `9.2`
|
25
|
+
|
26
|
+
It **should** work on MRI `2.3.x` too, but there's no official support for this version.
|
18
27
|
|
19
28
|
## License
|
20
29
|
|
data/lib/dry-schema.rb
CHANGED
data/lib/dry/schema.rb
CHANGED
data/lib/dry/schema/compiler.rb
CHANGED
data/lib/dry/schema/config.rb
CHANGED
data/lib/dry/schema/constants.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/core/constants'
|
2
4
|
|
3
5
|
module Dry
|
@@ -7,7 +9,7 @@ module Dry
|
|
7
9
|
InvalidSchemaError = Class.new(StandardError)
|
8
10
|
MissingMessageError = Class.new(StandardError)
|
9
11
|
|
10
|
-
QUESTION_MARK = '?'
|
11
|
-
DOT = '.'
|
12
|
+
QUESTION_MARK = '?'
|
13
|
+
DOT = '.'
|
12
14
|
end
|
13
15
|
end
|
data/lib/dry/schema/dsl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/initializer'
|
2
4
|
|
3
5
|
require 'dry/schema/constants'
|
@@ -72,7 +74,7 @@ module Dry
|
|
72
74
|
|
73
75
|
# @!attribute [r] config
|
74
76
|
# @return [Config] Configuration object exposed via `#configure` method
|
75
|
-
option :config, optional: true, default:
|
77
|
+
option :config, optional: true, default: proc { parent ? parent.config.dup : Config.new }
|
76
78
|
|
77
79
|
# Build a new DSL object and evaluate provided block
|
78
80
|
#
|
@@ -203,7 +205,7 @@ module Dry
|
|
203
205
|
#
|
204
206
|
# @api public
|
205
207
|
def array
|
206
|
-
-> member_type { type_registry[
|
208
|
+
-> member_type { type_registry['array'].of(resolve_type(member_type)) }
|
207
209
|
end
|
208
210
|
|
209
211
|
# Return type schema used by the value coercer
|
@@ -212,7 +214,7 @@ module Dry
|
|
212
214
|
#
|
213
215
|
# @api private
|
214
216
|
def type_schema
|
215
|
-
type_registry[
|
217
|
+
type_registry['hash'].schema(types.merge(parent_types)).safe
|
216
218
|
end
|
217
219
|
|
218
220
|
# Return a new DSL instance using the same processor type
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dry
|
2
4
|
module Schema
|
3
5
|
module Extensions
|
@@ -30,14 +32,19 @@ module Dry
|
|
30
32
|
# @api private
|
31
33
|
def exclude?(messages, opts)
|
32
34
|
Array(messages).all? do |msg|
|
33
|
-
hints = opts
|
35
|
+
hints = opts
|
36
|
+
.hints
|
37
|
+
.reject { |hint| msg == hint }
|
38
|
+
.reject { |hint| hint.predicate == :filled? }
|
39
|
+
|
34
40
|
key_failure = opts.key_failure?(msg.path)
|
35
41
|
predicate = msg.predicate
|
36
42
|
|
37
43
|
(HINT_TYPE_EXCLUSION.include?(predicate) && !key_failure) ||
|
38
44
|
(msg.predicate == :filled? && key_failure) ||
|
39
|
-
|
40
|
-
|
45
|
+
(!key_failure && HINT_TYPE_EXCLUSION.include?(predicate) &&
|
46
|
+
!hints.empty? && hints.any? { |hint| hint.path == msg.path }) ||
|
47
|
+
HINT_OTHER_EXCLUSION.include?(predicate)
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/monads/result'
|
2
4
|
|
3
5
|
module Dry
|
@@ -9,10 +11,9 @@ module Dry
|
|
9
11
|
if success?
|
10
12
|
Success(output)
|
11
13
|
else
|
12
|
-
Failure(
|
14
|
+
Failure(message_set(options).dump)
|
13
15
|
end
|
14
16
|
end
|
15
|
-
alias_method :to_result, :to_monad
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
data/lib/dry/schema/json.rb
CHANGED
data/lib/dry/schema/key.rb
CHANGED
data/lib/dry/schema/key_map.rb
CHANGED
data/lib/dry/schema/macros.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/schema/macros/dsl'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Schema
|
7
|
+
module Macros
|
8
|
+
# Macro used to specify predicates for each element of an array
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
class Array < DSL
|
12
|
+
# @api private
|
13
|
+
def value(*args, &block)
|
14
|
+
schema_dsl.set_type(name, :array)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
def to_ast(*)
|
20
|
+
[:and, [trace.array?.to_ast, [:each, trace.to_ast]]]
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :ast, :to_ast
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/logic/operators'
|
2
4
|
|
3
5
|
require 'dry/schema/macros/core'
|
@@ -68,8 +70,7 @@ module Dry
|
|
68
70
|
#
|
69
71
|
# @api public
|
70
72
|
def array(*args, &block)
|
71
|
-
|
72
|
-
append_macro(Macros::Each) do |macro|
|
73
|
+
append_macro(Macros::Array) do |macro|
|
73
74
|
macro.value(*args, &block)
|
74
75
|
end
|
75
76
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/schema/macros/value'
|
2
4
|
|
3
5
|
module Dry
|
@@ -9,11 +11,11 @@ module Dry
|
|
9
11
|
class Filled < Value
|
10
12
|
def call(*predicates, **opts, &block)
|
11
13
|
if predicates.include?(:empty?)
|
12
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
14
|
+
raise ::Dry::Schema::InvalidSchemaError, 'Using filled with empty? predicate is invalid'
|
13
15
|
end
|
14
16
|
|
15
17
|
if predicates.include?(:filled?)
|
16
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
18
|
+
raise ::Dry::Schema::InvalidSchemaError, 'Using filled with filled? is redundant'
|
17
19
|
end
|
18
20
|
|
19
21
|
if opts[:type_spec].equal?(true)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/schema/predicate_inferrer'
|
2
4
|
require 'dry/schema/processor'
|
3
5
|
require 'dry/schema/macros/dsl'
|
@@ -104,9 +106,11 @@ module Dry
|
|
104
106
|
def extract_type_spec(*args, nullable: false)
|
105
107
|
type_spec = args[0]
|
106
108
|
|
107
|
-
|
108
|
-
|
109
|
-
|
109
|
+
is_type_spec = type_spec.kind_of?(Dry::Schema::Processor) ||
|
110
|
+
type_spec.is_a?(Symbol) &&
|
111
|
+
type_spec.to_s.end_with?(QUESTION_MARK)
|
112
|
+
|
113
|
+
type_spec = nil if is_type_spec
|
110
114
|
|
111
115
|
predicates = Array(type_spec ? args[1..-1] : args)
|
112
116
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/schema/macros/dsl'
|
2
4
|
|
3
5
|
module Dry
|
@@ -10,11 +12,11 @@ module Dry
|
|
10
12
|
# @api private
|
11
13
|
def call(*args, **opts, &block)
|
12
14
|
if args.include?(:empty?)
|
13
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
15
|
+
raise ::Dry::Schema::InvalidSchemaError, 'Using maybe with empty? predicate is invalid'
|
14
16
|
end
|
15
17
|
|
16
18
|
if args.include?(:nil?)
|
17
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
19
|
+
raise ::Dry::Schema::InvalidSchemaError, 'Using maybe with nil? predicate is redundant'
|
18
20
|
end
|
19
21
|
|
20
22
|
value(*args, **opts, &block)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/schema/macros/dsl'
|
2
4
|
|
3
5
|
module Dry
|
@@ -13,13 +15,18 @@ module Dry
|
|
13
15
|
|
14
16
|
if schema
|
15
17
|
current_type = schema_dsl.types[name]
|
16
|
-
|
18
|
+
|
19
|
+
updated_type =
|
20
|
+
if current_type.respond_to?(:of)
|
21
|
+
current_type.of(schema.type_schema)
|
22
|
+
else
|
23
|
+
schema.type_schema
|
24
|
+
end
|
17
25
|
|
18
26
|
schema_dsl.set_type(name, updated_type)
|
19
27
|
end
|
20
28
|
|
21
|
-
trace.evaluate(*predicates, **opts
|
22
|
-
|
29
|
+
trace.evaluate(*predicates, **opts)
|
23
30
|
trace.append(new(chain: false).instance_exec(&block)) if block
|
24
31
|
|
25
32
|
if trace.captures.empty?
|
data/lib/dry/schema/message.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/equalizer'
|
4
|
+
require 'dry/schema/path'
|
2
5
|
|
3
6
|
module Dry
|
4
7
|
module Schema
|
@@ -86,6 +89,17 @@ module Dry
|
|
86
89
|
def eql?(other)
|
87
90
|
other.is_a?(String) ? text == other : super
|
88
91
|
end
|
92
|
+
|
93
|
+
def <=>(other)
|
94
|
+
l_path = Path[path]
|
95
|
+
r_path = Path[other.path]
|
96
|
+
|
97
|
+
unless l_path.include?(r_path)
|
98
|
+
raise ArgumentError, 'Cannot compare messages from different root paths'
|
99
|
+
end
|
100
|
+
|
101
|
+
l_path <=> r_path
|
102
|
+
end
|
89
103
|
end
|
90
104
|
end
|
91
105
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/schema/constants'
|
2
4
|
require 'dry/schema/message'
|
3
5
|
require 'dry/schema/message_set'
|
@@ -12,7 +14,7 @@ module Dry
|
|
12
14
|
attr_reader :messages, :options, :locale, :default_lookup_options
|
13
15
|
|
14
16
|
EMPTY_OPTS = VisitorOpts.new
|
15
|
-
LIST_SEPARATOR = ', '
|
17
|
+
LIST_SEPARATOR = ', '
|
16
18
|
|
17
19
|
# @api private
|
18
20
|
def initialize(messages, options = {})
|
@@ -83,7 +85,7 @@ module Dry
|
|
83
85
|
elsif right.is_a?(Array)
|
84
86
|
right
|
85
87
|
else
|
86
|
-
[left, right]
|
88
|
+
[left, right].flatten.max
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
data/lib/dry/schema/messages.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
require 'concurrent/map'
|
3
5
|
require 'dry/equalizer'
|
@@ -19,7 +21,7 @@ module Dry
|
|
19
21
|
DEFAULT_PATH = Pathname(__dir__).join('../../../../config/errors.yml').realpath.freeze
|
20
22
|
|
21
23
|
setting :paths, [DEFAULT_PATH]
|
22
|
-
setting :root, 'errors'
|
24
|
+
setting :root, 'errors'
|
23
25
|
setting :lookup_options, [:root, :predicate, :path, :val_type, :arg_type].freeze
|
24
26
|
|
25
27
|
setting :lookup_paths, %w(
|
@@ -38,8 +40,8 @@ module Dry
|
|
38
40
|
rules.%{name}
|
39
41
|
).freeze
|
40
42
|
|
41
|
-
setting :arg_type_default, 'default'
|
42
|
-
setting :val_type_default, 'default'
|
43
|
+
setting :arg_type_default, 'default'
|
44
|
+
setting :val_type_default, 'default'
|
43
45
|
|
44
46
|
setting :arg_types, Hash.new { |*| config.arg_type_default }.update(
|
45
47
|
Range => 'range'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'i18n'
|
2
4
|
require 'dry/schema/messages/abstract'
|
3
5
|
|
@@ -10,7 +12,7 @@ module Dry
|
|
10
12
|
attr_reader :t
|
11
13
|
|
12
14
|
configure do |config|
|
13
|
-
config.root = 'dry_schema.errors'
|
15
|
+
config.root = 'dry_schema.errors'
|
14
16
|
config.rule_lookup_paths = config.rule_lookup_paths.map { |path| "dry_schema.#{path}" }
|
15
17
|
end
|
16
18
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dry
|
2
4
|
module Schema
|
3
5
|
module Messages
|
@@ -60,7 +62,7 @@ module Dry
|
|
60
62
|
|
61
63
|
def rule_lookup_paths(tokens)
|
62
64
|
base_paths = messages.rule_lookup_paths(tokens)
|
63
|
-
base_paths.map { |key| key.gsub(
|
65
|
+
base_paths.map { |key| key.gsub('dry_schema', "dry_schema.#{namespace}") } + base_paths
|
64
66
|
end
|
65
67
|
end
|
66
68
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
require 'pathname'
|
3
5
|
|
@@ -16,8 +18,10 @@ module Dry
|
|
16
18
|
|
17
19
|
# @api private
|
18
20
|
configure do |config|
|
19
|
-
config.root = '%{locale}.dry_schema.errors'
|
20
|
-
config.rule_lookup_paths = config.rule_lookup_paths.map { |path|
|
21
|
+
config.root = '%{locale}.dry_schema.errors'
|
22
|
+
config.rule_lookup_paths = config.rule_lookup_paths.map { |path|
|
23
|
+
"%{locale}.dry_schema.#{path}"
|
24
|
+
}
|
21
25
|
end
|
22
26
|
|
23
27
|
# @api private
|
@@ -32,7 +36,7 @@ module Dry
|
|
32
36
|
|
33
37
|
# @api private
|
34
38
|
def self.flat_hash(h, f = [], g = {})
|
35
|
-
return g.update(f.join('.'
|
39
|
+
return g.update(f.join('.') => h) unless h.is_a? Hash
|
36
40
|
h.each { |k, r| flat_hash(r, f + [k], g) }
|
37
41
|
g
|
38
42
|
end
|
data/lib/dry/schema/params.rb
CHANGED
data/lib/dry/schema/path.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/schema/constants'
|
2
4
|
|
3
5
|
module Dry
|
@@ -6,6 +8,8 @@ module Dry
|
|
6
8
|
#
|
7
9
|
# @api private
|
8
10
|
class Path
|
11
|
+
include Enumerable
|
12
|
+
|
9
13
|
# !@attribute [r] keys
|
10
14
|
# @return [Array<Symbol>]
|
11
15
|
attr_reader :keys
|
@@ -47,8 +51,23 @@ module Dry
|
|
47
51
|
end
|
48
52
|
|
49
53
|
# @api private
|
50
|
-
def
|
51
|
-
keys
|
54
|
+
def each(&block)
|
55
|
+
keys.each(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def index(key)
|
60
|
+
keys.index(key)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
def include?(other)
|
65
|
+
!find { |key| (idx = other.index(key)) && keys[idx].equal?(key) }.nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
def <=>(other)
|
70
|
+
keys.count <=> other.count
|
52
71
|
end
|
53
72
|
end
|
54
73
|
end
|
data/lib/dry/schema/predicate.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/core/cache'
|
2
4
|
|
3
5
|
module Dry
|
@@ -9,23 +11,71 @@ module Dry
|
|
9
11
|
class PredicateInferrer
|
10
12
|
extend Dry::Core::Cache
|
11
13
|
|
12
|
-
TYPE_TO_PREDICATE =
|
13
|
-
primitive = type.meta[:maybe] ? type.right.primitive : type.primitive
|
14
|
-
|
15
|
-
if hash.key?(primitive)
|
16
|
-
hash[primitive]
|
17
|
-
else
|
18
|
-
:"#{primitive.name.split('::').last.downcase}?"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
TYPE_TO_PREDICATE.update(
|
14
|
+
TYPE_TO_PREDICATE = {
|
23
15
|
FalseClass => :false?,
|
24
16
|
Integer => :int?,
|
25
17
|
NilClass => :nil?,
|
26
18
|
String => :str?,
|
27
19
|
TrueClass => :true?
|
28
|
-
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
REDUCED_TYPES = {
|
23
|
+
%i[true? false?] => :bool?
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
# Compiler reduces type AST into a list of predicates
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
class Compiler
|
30
|
+
def visit(node)
|
31
|
+
meth, rest = node
|
32
|
+
public_send(:"visit_#{meth}", rest)
|
33
|
+
end
|
34
|
+
|
35
|
+
def visit_definition(node)
|
36
|
+
type = node[0]
|
37
|
+
|
38
|
+
TYPE_TO_PREDICATE.fetch(type) {
|
39
|
+
:"#{type.name.split('::').last.downcase}?"
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def visit_array(*)
|
44
|
+
:array?
|
45
|
+
end
|
46
|
+
|
47
|
+
def visit_safe(node)
|
48
|
+
other, * = node
|
49
|
+
visit(other)
|
50
|
+
end
|
51
|
+
|
52
|
+
def visit_constructor(node)
|
53
|
+
other, * = node
|
54
|
+
visit(other)
|
55
|
+
end
|
56
|
+
|
57
|
+
def visit_enum(node)
|
58
|
+
other, * = node
|
59
|
+
visit(other)
|
60
|
+
end
|
61
|
+
|
62
|
+
def visit_sum(node)
|
63
|
+
left, right = node
|
64
|
+
|
65
|
+
predicates = [visit(left), visit(right)]
|
66
|
+
|
67
|
+
if predicates.first == :nil?
|
68
|
+
predicates[1..predicates.size - 1]
|
69
|
+
else
|
70
|
+
predicates
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def visit_constrained(node)
|
75
|
+
other, * = node
|
76
|
+
visit(other)
|
77
|
+
end
|
78
|
+
end
|
29
79
|
|
30
80
|
# Infer predicate identifier from the provided type
|
31
81
|
#
|
@@ -34,16 +84,15 @@ module Dry
|
|
34
84
|
# @api private
|
35
85
|
def self.[](type)
|
36
86
|
fetch_or_store(type.hash) {
|
37
|
-
predicates =
|
38
|
-
|
39
|
-
[self[type.left], self[type.right]]
|
40
|
-
else
|
41
|
-
TYPE_TO_PREDICATE[type]
|
42
|
-
end
|
43
|
-
|
44
|
-
Array(predicates).flatten
|
87
|
+
predicates = Array(compiler.visit(type.to_ast)).flatten
|
88
|
+
Array(REDUCED_TYPES[predicates] || predicates).flatten
|
45
89
|
}
|
46
90
|
end
|
91
|
+
|
92
|
+
# @api private
|
93
|
+
def self.compiler
|
94
|
+
@compiler ||= Compiler.new
|
95
|
+
end
|
47
96
|
end
|
48
97
|
end
|
49
98
|
end
|
data/lib/dry/schema/processor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/configurable'
|
2
4
|
require 'dry/initializer'
|
3
5
|
|
@@ -113,6 +115,15 @@ module Dry
|
|
113
115
|
@__type_schema__ ||= steps.detect { |s| s.is_a?(ValueCoercer) }.type_schema
|
114
116
|
end
|
115
117
|
|
118
|
+
# Return the rules config
|
119
|
+
#
|
120
|
+
# @return [Dry::Types::Config]
|
121
|
+
#
|
122
|
+
# @api private
|
123
|
+
def config
|
124
|
+
@__config__ ||= steps.detect { |s| s.is_a?(RuleApplier) }.config
|
125
|
+
end
|
126
|
+
|
116
127
|
# Return AST representation of the rules
|
117
128
|
#
|
118
129
|
# @api private
|
data/lib/dry/schema/result.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/initializer'
|
2
4
|
require 'dry/equalizer'
|
3
5
|
|
@@ -76,7 +78,7 @@ module Dry
|
|
76
78
|
#
|
77
79
|
# @api public
|
78
80
|
def error?(spec)
|
79
|
-
message_set.any? { |msg| Path[
|
81
|
+
message_set.any? { |msg| Path[msg.path].include?(Path[spec]) }
|
80
82
|
end
|
81
83
|
|
82
84
|
# Check if the result is successful
|
data/lib/dry/schema/trace.rb
CHANGED
data/lib/dry/schema/types.rb
CHANGED
data/lib/dry/schema/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.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-
|
11
|
+
date: 2019-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -44,6 +44,26 @@ dependencies:
|
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 0.1.3
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: dry-core
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.2'
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.2.1
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0.2'
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.2.1
|
47
67
|
- !ruby/object:Gem::Dependency
|
48
68
|
name: dry-equalizer
|
49
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,26 +132,6 @@ dependencies:
|
|
112
132
|
- - "~>"
|
113
133
|
- !ruby/object:Gem::Version
|
114
134
|
version: '0.14'
|
115
|
-
- !ruby/object:Gem::Dependency
|
116
|
-
name: dry-core
|
117
|
-
requirement: !ruby/object:Gem::Requirement
|
118
|
-
requirements:
|
119
|
-
- - "~>"
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
version: '0.2'
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 0.2.1
|
125
|
-
type: :runtime
|
126
|
-
prerelease: false
|
127
|
-
version_requirements: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0.2'
|
132
|
-
- - ">="
|
133
|
-
- !ruby/object:Gem::Version
|
134
|
-
version: 0.2.1
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: bundler
|
137
137
|
requirement: !ruby/object:Gem::Requirement
|
@@ -202,6 +202,7 @@ files:
|
|
202
202
|
- lib/dry/schema/key_coercer.rb
|
203
203
|
- lib/dry/schema/key_map.rb
|
204
204
|
- lib/dry/schema/macros.rb
|
205
|
+
- lib/dry/schema/macros/array.rb
|
205
206
|
- lib/dry/schema/macros/core.rb
|
206
207
|
- lib/dry/schema/macros/dsl.rb
|
207
208
|
- lib/dry/schema/macros/each.rb
|
@@ -249,7 +250,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
249
250
|
requirements:
|
250
251
|
- - ">="
|
251
252
|
- !ruby/object:Gem::Version
|
252
|
-
version: '2.
|
253
|
+
version: '2.3'
|
253
254
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
254
255
|
requirements:
|
255
256
|
- - ">="
|