dry-types 0.9.0 → 0.15.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 +5 -5
- data/.codeclimate.yml +15 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +43 -0
- data/.travis.yml +15 -14
- data/.yardopts +5 -0
- data/CHANGELOG.md +494 -88
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +7 -6
- data/README.md +1 -3
- data/Rakefile +8 -3
- data/benchmarks/hash_schemas.rb +7 -7
- data/dry-types.gemspec +11 -9
- data/lib/dry/types/any.rb +36 -0
- data/lib/dry/types/array/member.rb +29 -4
- data/lib/dry/types/array.rb +6 -4
- data/lib/dry/types/builder.rb +48 -6
- data/lib/dry/types/builder_methods.rb +111 -0
- data/lib/dry/types/coercions/json.rb +3 -0
- data/lib/dry/types/coercions/{form.rb → params.rb} +23 -3
- data/lib/dry/types/coercions.rb +16 -3
- data/lib/dry/types/compat.rb +0 -0
- data/lib/dry/types/compiler.rb +66 -39
- data/lib/dry/types/constrained/coercible.rb +7 -1
- data/lib/dry/types/constrained.rb +42 -3
- data/lib/dry/types/constraints.rb +3 -0
- data/lib/dry/types/constructor.rb +98 -16
- data/lib/dry/types/container.rb +2 -0
- data/lib/dry/types/core.rb +30 -14
- data/lib/dry/types/decorator.rb +31 -5
- data/lib/dry/types/default.rb +34 -8
- data/lib/dry/types/enum.rb +71 -14
- data/lib/dry/types/errors.rb +23 -6
- data/lib/dry/types/extensions/maybe.rb +35 -16
- data/lib/dry/types/fn_container.rb +34 -0
- data/lib/dry/types/hash/constructor.rb +20 -0
- data/lib/dry/types/hash.rb +103 -23
- data/lib/dry/types/inflector.rb +7 -0
- data/lib/dry/types/json.rb +7 -7
- data/lib/dry/types/map.rb +98 -0
- data/lib/dry/types/module.rb +115 -0
- data/lib/dry/types/nominal.rb +119 -0
- data/lib/dry/types/options.rb +29 -7
- data/lib/dry/types/params.rb +53 -0
- data/lib/dry/types/printable.rb +12 -0
- data/lib/dry/types/printer.rb +309 -0
- data/lib/dry/types/result.rb +12 -2
- data/lib/dry/types/safe.rb +27 -1
- data/lib/dry/types/schema/key.rb +130 -0
- data/lib/dry/types/schema.rb +298 -0
- data/lib/dry/types/spec/types.rb +102 -0
- data/lib/dry/types/sum.rb +75 -13
- data/lib/dry/types/type.rb +6 -0
- data/lib/dry/types/version.rb +1 -1
- data/lib/dry/types.rb +104 -38
- data/log/.gitkeep +0 -0
- metadata +81 -50
- data/lib/dry/types/definition.rb +0 -79
- data/lib/dry/types/form.rb +0 -53
- data/lib/dry/types/hash/schema.rb +0 -156
- data/lib/spec/dry/types.rb +0 -56
data/lib/dry/types/definition.rb
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
require 'dry/types/builder'
|
|
2
|
-
require 'dry/types/result'
|
|
3
|
-
require 'dry/types/options'
|
|
4
|
-
|
|
5
|
-
module Dry
|
|
6
|
-
module Types
|
|
7
|
-
class Definition
|
|
8
|
-
include Dry::Equalizer(:primitive, :options)
|
|
9
|
-
include Options
|
|
10
|
-
include Builder
|
|
11
|
-
|
|
12
|
-
attr_reader :options
|
|
13
|
-
|
|
14
|
-
attr_reader :primitive
|
|
15
|
-
|
|
16
|
-
def self.[](primitive)
|
|
17
|
-
if primitive == ::Array
|
|
18
|
-
Types::Array
|
|
19
|
-
elsif primitive == ::Hash
|
|
20
|
-
Types::Hash
|
|
21
|
-
else
|
|
22
|
-
self
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def initialize(primitive, options = {})
|
|
27
|
-
super
|
|
28
|
-
@primitive = primitive
|
|
29
|
-
freeze
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def name
|
|
33
|
-
primitive.name
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def default?
|
|
37
|
-
false
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def constrained?
|
|
41
|
-
false
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def call(input)
|
|
45
|
-
input
|
|
46
|
-
end
|
|
47
|
-
alias_method :[], :call
|
|
48
|
-
|
|
49
|
-
def try(input, &block)
|
|
50
|
-
if valid?(input)
|
|
51
|
-
success(input)
|
|
52
|
-
else
|
|
53
|
-
failure = failure(input, "#{input.inspect} must be an instance of #{primitive}")
|
|
54
|
-
block ? yield(failure) : failure
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def success(*args)
|
|
59
|
-
result(Result::Success, *args)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def failure(*args)
|
|
63
|
-
result(Result::Failure, *args)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def result(klass, *args)
|
|
67
|
-
klass.new(*args)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def primitive?(value)
|
|
71
|
-
value.is_a?(primitive)
|
|
72
|
-
end
|
|
73
|
-
alias_method :valid?, :primitive?
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
require 'dry/types/array'
|
|
79
|
-
require 'dry/types/hash'
|
data/lib/dry/types/form.rb
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
require 'dry/types/coercions/form'
|
|
2
|
-
|
|
3
|
-
module Dry
|
|
4
|
-
module Types
|
|
5
|
-
register('form.nil') do
|
|
6
|
-
self['nil'].constructor(Coercions::Form.method(:to_nil))
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
register('form.date') do
|
|
10
|
-
self['date'].constructor(Coercions::Form.method(:to_date))
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
register('form.date_time') do
|
|
14
|
-
self['date_time'].constructor(Coercions::Form.method(:to_date_time))
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
register('form.time') do
|
|
18
|
-
self['time'].constructor(Coercions::Form.method(:to_time))
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
register('form.true') do
|
|
22
|
-
self['true'].constructor(Coercions::Form.method(:to_true))
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
register('form.false') do
|
|
26
|
-
self['false'].constructor(Coercions::Form.method(:to_false))
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
register('form.bool') do
|
|
30
|
-
(self['form.true'] | self['form.false']).safe
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
register('form.int') do
|
|
34
|
-
self['int'].constructor(Coercions::Form.method(:to_int))
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
register('form.float') do
|
|
38
|
-
self['float'].constructor(Coercions::Form.method(:to_float))
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
register('form.decimal') do
|
|
42
|
-
self['decimal'].constructor(Coercions::Form.method(:to_decimal))
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
register('form.array') do
|
|
46
|
-
self['array'].constructor(Coercions::Form.method(:to_ary)).safe
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
register('form.hash') do
|
|
50
|
-
self['hash'].constructor(Coercions::Form.method(:to_hash)).safe
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
module Dry
|
|
2
|
-
module Types
|
|
3
|
-
class Hash < Definition
|
|
4
|
-
class Schema < Hash
|
|
5
|
-
attr_reader :member_types
|
|
6
|
-
|
|
7
|
-
def initialize(_primitive, options)
|
|
8
|
-
@member_types = options.fetch(:member_types)
|
|
9
|
-
super
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def call(hash)
|
|
13
|
-
coerce(hash)
|
|
14
|
-
end
|
|
15
|
-
alias_method :[], :call
|
|
16
|
-
|
|
17
|
-
def try(hash, &block)
|
|
18
|
-
success = true
|
|
19
|
-
output = {}
|
|
20
|
-
|
|
21
|
-
begin
|
|
22
|
-
result = try_coerce(hash) do |key, member_result|
|
|
23
|
-
success &&= member_result.success?
|
|
24
|
-
output[key] = member_result.input
|
|
25
|
-
|
|
26
|
-
member_result
|
|
27
|
-
end
|
|
28
|
-
rescue ConstraintError, UnknownKeysError, SchemaError => e
|
|
29
|
-
success = false
|
|
30
|
-
result = e
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
if success
|
|
34
|
-
success(output)
|
|
35
|
-
else
|
|
36
|
-
failure = failure(output, result)
|
|
37
|
-
block ? yield(failure) : failure
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def try_coerce(hash)
|
|
44
|
-
resolve(hash) do |type, key, value|
|
|
45
|
-
yield(key, type.try(value))
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def coerce(hash)
|
|
50
|
-
resolve(hash) do |type, key, value|
|
|
51
|
-
begin
|
|
52
|
-
type.call(value)
|
|
53
|
-
rescue ConstraintError
|
|
54
|
-
raise SchemaError.new(key, value)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def resolve(hash)
|
|
60
|
-
member_types.each_with_object({}) do |(key, type), result|
|
|
61
|
-
if hash.key?(key)
|
|
62
|
-
result[key] = yield(type, key, hash[key])
|
|
63
|
-
else
|
|
64
|
-
resolve_missing_value(result, key, type)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def resolve_missing_value(result, key, type)
|
|
70
|
-
if type.default?
|
|
71
|
-
result[key] = type.evaluate
|
|
72
|
-
else
|
|
73
|
-
super
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
class Permissive < Schema
|
|
79
|
-
private
|
|
80
|
-
|
|
81
|
-
def resolve_missing_value(_, key, _)
|
|
82
|
-
raise MissingKeyError, key
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
class Strict < Permissive
|
|
87
|
-
private
|
|
88
|
-
|
|
89
|
-
def resolve(hash)
|
|
90
|
-
unexpected = hash.keys - member_types.keys
|
|
91
|
-
raise UnknownKeysError.new(*unexpected) unless unexpected.empty?
|
|
92
|
-
|
|
93
|
-
super do |member_type, key, value|
|
|
94
|
-
type = member_type.default? ? member_type.type : member_type
|
|
95
|
-
|
|
96
|
-
yield(type, key, value)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
class StrictWithDefaults < Strict
|
|
102
|
-
private
|
|
103
|
-
|
|
104
|
-
def resolve_missing_value(result, key, type)
|
|
105
|
-
if type.default?
|
|
106
|
-
result[key] = type.value
|
|
107
|
-
else
|
|
108
|
-
super
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
class Weak < Schema
|
|
114
|
-
def self.new(primitive, options)
|
|
115
|
-
member_types = options.
|
|
116
|
-
fetch(:member_types).
|
|
117
|
-
each_with_object({}) { |(k, t), res| res[k] = t.safe }
|
|
118
|
-
|
|
119
|
-
super(primitive, options.merge(member_types: member_types))
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def try(hash, &block)
|
|
123
|
-
if hash.instance_of?(::Hash)
|
|
124
|
-
super
|
|
125
|
-
else
|
|
126
|
-
result = failure(hash, "#{hash} must be a hash")
|
|
127
|
-
block ? yield(result) : result
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
class Symbolized < Weak
|
|
133
|
-
private
|
|
134
|
-
|
|
135
|
-
def resolve(hash)
|
|
136
|
-
member_types.each_with_object({}) do |(key, type), result|
|
|
137
|
-
keyname =
|
|
138
|
-
if hash.key?(key)
|
|
139
|
-
key
|
|
140
|
-
elsif hash.key?(string_key = key.to_s)
|
|
141
|
-
string_key
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
if keyname
|
|
145
|
-
result[key] = yield(type, key, hash[keyname])
|
|
146
|
-
else
|
|
147
|
-
resolve_missing_value(result, key, type)
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
private_constant(*constants(false))
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
data/lib/spec/dry/types.rb
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
RSpec.shared_examples_for 'Dry::Types::Definition without primitive' do
|
|
2
|
-
def be_boolean
|
|
3
|
-
satisfy { |x| x == true || x == false }
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
describe '#constrained?' do
|
|
7
|
-
it 'returns a boolean value' do
|
|
8
|
-
expect(type.constrained?).to be_boolean
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
describe '#default?' do
|
|
13
|
-
it 'returns a boolean value' do
|
|
14
|
-
expect(type.default?).to be_boolean
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
describe '#valid?' do
|
|
19
|
-
it 'returns a boolean value' do
|
|
20
|
-
expect(type.valid?(1)).to be_boolean
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
describe '#eql?' do
|
|
25
|
-
it 'has #eql? defined' do
|
|
26
|
-
expect(type).to eql(type)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
describe '#==' do
|
|
31
|
-
it 'has #== defined' do
|
|
32
|
-
expect(type).to eq(type)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
RSpec.shared_examples_for 'Dry::Types::Definition#meta' do
|
|
38
|
-
describe '#meta' do
|
|
39
|
-
it 'allows setting meta information' do
|
|
40
|
-
with_meta = type.meta(foo: :bar).meta(baz: '1')
|
|
41
|
-
|
|
42
|
-
expect(with_meta).to be_instance_of(type.class)
|
|
43
|
-
expect(with_meta.meta).to eql(foo: :bar, baz: '1')
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
RSpec.shared_examples_for Dry::Types::Definition do
|
|
49
|
-
it_behaves_like 'Dry::Types::Definition without primitive'
|
|
50
|
-
|
|
51
|
-
describe '#primitive' do
|
|
52
|
-
it 'returns a class' do
|
|
53
|
-
expect(type.primitive).to be_instance_of(Class)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|