dry-types 1.0.1 → 1.1.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 +33 -3
- data/Gemfile +4 -3
- data/Rakefile +2 -2
- data/benchmarks/hash_schemas.rb +8 -6
- data/benchmarks/lax_schema.rb +0 -1
- data/benchmarks/profile_invalid_input.rb +1 -1
- data/benchmarks/profile_lax_schema_valid.rb +1 -1
- data/benchmarks/profile_valid_input.rb +1 -1
- data/dry-types.gemspec +19 -19
- data/lib/dry/types.rb +2 -2
- data/lib/dry/types/array.rb +6 -0
- data/lib/dry/types/array/constructor.rb +32 -0
- data/lib/dry/types/array/member.rb +7 -0
- data/lib/dry/types/builder.rb +1 -1
- data/lib/dry/types/builder_methods.rb +15 -15
- data/lib/dry/types/coercions.rb +19 -6
- data/lib/dry/types/coercions/params.rb +4 -4
- data/lib/dry/types/constrained.rb +5 -0
- data/lib/dry/types/constructor.rb +3 -8
- data/lib/dry/types/constructor/function.rb +4 -5
- data/lib/dry/types/core.rb +27 -8
- data/lib/dry/types/enum.rb +1 -0
- data/lib/dry/types/extensions/maybe.rb +9 -1
- data/lib/dry/types/hash.rb +8 -10
- data/lib/dry/types/hash/constructor.rb +5 -5
- data/lib/dry/types/json.rb +4 -0
- data/lib/dry/types/lax.rb +3 -3
- data/lib/dry/types/map.rb +8 -4
- data/lib/dry/types/module.rb +3 -3
- data/lib/dry/types/nominal.rb +3 -4
- data/lib/dry/types/params.rb +4 -0
- data/lib/dry/types/printer.rb +11 -10
- data/lib/dry/types/schema.rb +14 -20
- data/lib/dry/types/schema/key.rb +19 -1
- data/lib/dry/types/spec/types.rb +3 -6
- data/lib/dry/types/version.rb +1 -1
- metadata +40 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 689634e9152c629af622ef69379633b674b6c60b7f5cd87093894de7ee8ce571
|
4
|
+
data.tar.gz: a23593e6c4d904343dadd46f919cfead42b45fbe963995380712f4c6a8e719fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88fd3e79ea403515fe242baa57c6824757bdc0b04f99054a9da2394c745cce54415fc3c260b35e49eed8a5240f78614efe92e052f6e6bde0e1f9b961a04f41ac
|
7
|
+
data.tar.gz: 3445b5726dd5325261965409883b6830450f3d710ae2b0a7be411b0d45cb25d3550a25827d9f0661dfbfd0fd55f15954d77335312237c3bf754ca7af5eae6079
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,30 @@
|
|
1
|
+
# 1.1.0 2019-07-02
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
- New builder method `Interface` constructs a type which accepts objects that respond to the given methods (waiting-for-dev)
|
6
|
+
```ruby
|
7
|
+
Types = Dry.Types()
|
8
|
+
Types::Callable = Types.Interface(:call)
|
9
|
+
Types::Callable.valid?(Object.new) # => false
|
10
|
+
Types::Callable.valid?(proc {}) # => true
|
11
|
+
```
|
12
|
+
- New types: `coercible.symbol`, `params.symbol`, and `json.symbol`, all use `.to_sym` for coercion (waiting-for-dev)
|
13
|
+
|
14
|
+
## Fixed
|
15
|
+
|
16
|
+
- Converting schema keys to maybe types (flash-gordon)
|
17
|
+
- Using `Schema#key` and `Array#member` on constuctors (flash-gordon)
|
18
|
+
- Using `meta(omittable: true)` within `transform_types` works again but produces a warning, please migrate to `.omittable` or `.required(false)` (flash-gordon)
|
19
|
+
- Bug with a constructror defined on top of enum (flash-gordon)
|
20
|
+
|
21
|
+
[Compare v1.0.1...v1.1.0](https://github.com/dry-rb/dry-types/compare/v1.0.1...v1.1.0)
|
22
|
+
|
1
23
|
# 1.0.1 2019-06-04
|
2
24
|
|
3
25
|
## Added
|
4
26
|
|
5
|
-
- In
|
27
|
+
- In a case of failure the constructor block can now pass a different value (flash-gordon)
|
6
28
|
```ruby
|
7
29
|
not_empty_string = Types::String.constructor do |value, &failure|
|
8
30
|
value.strip.empty? ? failure.(nil) : value.strip
|
@@ -21,6 +43,7 @@
|
|
21
43
|
|
22
44
|
- [BREAKING] Behavior of built-in constructor types was changed to be more strict. They will always raise an error on failed coercion (flash-gordon)
|
23
45
|
Compare:
|
46
|
+
|
24
47
|
```ruby
|
25
48
|
# 0.15.0
|
26
49
|
Types::Params::Integer.('foo')
|
@@ -36,7 +59,9 @@
|
|
36
59
|
```ruby
|
37
60
|
Types::Params::Integer.('foo') { :invalid } # => :invalid
|
38
61
|
```
|
62
|
+
|
39
63
|
This makes work with coercions more straightforward and way faster.
|
64
|
+
|
40
65
|
- [BREAKING] Safe types were renamed to Lax, this name better serves their purpose. The previous name is available but prints a warning (flash-gordon)
|
41
66
|
- [BREAKING] Metadata is now pushed down to the decorated type. It is not likely you will notice a difference but this a breaking change that enables some use cases in rom related to the usage of default types in relations (flash-gordon)
|
42
67
|
- Nominal types are now completely unconstrained. This fixes some inconsistencies when using them with constraints. `Nominal#try` will always return a successful result, for the previous behavior use `Nominal#try_coerce` or switch to strict types with passing a block to `#call` (flash-gordon)
|
@@ -159,6 +184,7 @@
|
|
159
184
|
)
|
160
185
|
```
|
161
186
|
- Key types have API for making keys omittable and back (flash-gordon)
|
187
|
+
|
162
188
|
```ruby
|
163
189
|
# defining a base schema with optional keys
|
164
190
|
lax_hash = Dry::Types['hash'].with_type_transform { |key| key.required(false) }
|
@@ -168,8 +194,10 @@
|
|
168
194
|
# keys in user_schema are not required
|
169
195
|
user_schema = lax_hash.schema(name: 'string', age: 'integer')
|
170
196
|
```
|
197
|
+
|
171
198
|
- `Type#optional?` now recognizes more cases where `nil` is an allowed value (flash-gordon)
|
172
199
|
- `Constructor#{prepend,append}` with `<<` and `>>` as aliases. `Constructor#append` works the same way `Constructor#constrcutor` does. `Constuctor#prepend` chains functions in the reverse order, see examples (flash-gordon)
|
200
|
+
|
173
201
|
```ruby
|
174
202
|
to_int = Types::Coercible::Integer
|
175
203
|
inc = to_int.append { |x| x + 2 }
|
@@ -178,6 +206,7 @@
|
|
178
206
|
inc = to_int.prepend { |x| x + "2" }
|
179
207
|
inc.("1") # => "1" -> "12" -> 12
|
180
208
|
```
|
209
|
+
|
181
210
|
- Partial schema application for cases when you want to validate only a subset of keys (flash-gordon)
|
182
211
|
This is useful when you want to update a key or two in an already-validated hash. A perfect example is `Dry::Struct#new` where this feature is now used.
|
183
212
|
```ruby
|
@@ -189,14 +218,15 @@
|
|
189
218
|
|
190
219
|
## Fixed
|
191
220
|
|
192
|
-
|
193
|
-
|
221
|
+
- `Hash::Map` now behaves as a constrained type if its values are constrained (flash-gordon)
|
222
|
+
- `coercible.integer` now doesn't blow up on invalid strings (exterm)
|
194
223
|
|
195
224
|
[Compare v0.14.0...v0.15.0](https://github.com/dry-rb/dry-types/compare/v0.14.0...v0.15.0)
|
196
225
|
|
197
226
|
# v0.14.1 2019-03-25
|
198
227
|
|
199
228
|
## Fixed
|
229
|
+
|
200
230
|
- `coercible.integer` now doesn't blow up on invalid strings (exterm)
|
201
231
|
|
202
232
|
[Compare v0.14.0...v0.14.1](https://github.com/dry-rb/dry-types/compare/v0.14.0...v0.14.1)
|
data/Gemfile
CHANGED
@@ -14,13 +14,14 @@ end
|
|
14
14
|
|
15
15
|
group :tools do
|
16
16
|
gem 'pry-byebug', platform: :mri
|
17
|
+
gem 'rubocop'
|
17
18
|
end
|
18
19
|
|
19
20
|
group :benchmarks do
|
21
|
+
gem 'attrio'
|
20
22
|
gem 'benchmark-ips'
|
23
|
+
gem 'dry-struct'
|
24
|
+
gem 'fast_attributes'
|
21
25
|
gem 'hotch'
|
22
26
|
gem 'virtus'
|
23
|
-
gem 'fast_attributes'
|
24
|
-
gem 'attrio'
|
25
|
-
gem 'dry-struct'
|
26
27
|
end
|
data/Rakefile
CHANGED
data/benchmarks/hash_schemas.rb
CHANGED
@@ -7,11 +7,13 @@ require 'dry-types'
|
|
7
7
|
|
8
8
|
module SchemaBench
|
9
9
|
def self.hash_schema(type)
|
10
|
-
Dry::Types['nominal.hash'].public_send(
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
Dry::Types['nominal.hash'].public_send(
|
11
|
+
type,
|
12
|
+
email: Dry::Types['nominal.string'],
|
13
|
+
age: Dry::Types['params.integer'],
|
14
|
+
admin: Dry::Types['params.bool'],
|
15
|
+
address: Dry::Types['nominal.hash'].public_send(
|
16
|
+
type,
|
15
17
|
city: Dry::Types['nominal.string'],
|
16
18
|
street: Dry::Types['nominal.string']
|
17
19
|
)
|
@@ -31,7 +33,7 @@ module SchemaBench
|
|
31
33
|
age: '20',
|
32
34
|
admin: '1',
|
33
35
|
address: { city: 'NYC', street: 'Street 1/2' }
|
34
|
-
}
|
36
|
+
}.freeze
|
35
37
|
end
|
36
38
|
|
37
39
|
require 'benchmark/ips'
|
data/benchmarks/lax_schema.rb
CHANGED
data/dry-types.gemspec
CHANGED
@@ -1,47 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'dry/types/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = 'dry-types'
|
9
9
|
spec.version = Dry::Types::VERSION.dup
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
10
|
+
spec.authors = ['Piotr Solnica']
|
11
|
+
spec.email = ['piotr.solnica@gmail.com']
|
12
12
|
spec.license = 'MIT'
|
13
13
|
|
14
14
|
spec.summary = 'Type system for Ruby supporting coercions, constraints and complex types like structs, value objects, enums etc.'
|
15
15
|
spec.description = spec.summary
|
16
|
-
spec.homepage =
|
16
|
+
spec.homepage = 'https://github.com/dry-rb/dry-types'
|
17
17
|
|
18
18
|
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
19
19
|
# delete this section to allow pushing this gem to any host.
|
20
20
|
if spec.respond_to?(:metadata)
|
21
|
-
spec.metadata['allowed_push_host'] =
|
22
|
-
spec.metadata['changelog_uri'] =
|
23
|
-
spec.metadata['source_code_uri'] =
|
24
|
-
spec.metadata['bug_tracker_uri'] =
|
21
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
22
|
+
spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md'
|
23
|
+
spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-types'
|
24
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-types/issues'
|
25
25
|
else
|
26
|
-
raise
|
26
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
27
27
|
end
|
28
28
|
|
29
29
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - ['bin/console', 'bin/setup']
|
30
|
-
spec.bindir =
|
30
|
+
spec.bindir = 'exe'
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
-
spec.require_paths = [
|
33
|
-
spec.required_ruby_version =
|
32
|
+
spec.require_paths = ['lib']
|
33
|
+
spec.required_ruby_version = '>= 2.4.0'
|
34
34
|
|
35
35
|
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
36
|
-
spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
|
37
|
-
spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
|
38
36
|
spec.add_runtime_dependency 'dry-container', '~> 0.3'
|
37
|
+
spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
|
39
38
|
spec.add_runtime_dependency 'dry-equalizer', '~> 0.2', '>= 0.2.2'
|
40
|
-
spec.add_runtime_dependency 'dry-
|
39
|
+
spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
|
40
|
+
spec.add_runtime_dependency 'dry-logic', '~> 1.0', '>= 1.0.2'
|
41
41
|
|
42
|
-
spec.add_development_dependency
|
43
|
-
spec.add_development_dependency "rake", "~> 11.0"
|
44
|
-
spec.add_development_dependency "rspec", "~> 3.3"
|
42
|
+
spec.add_development_dependency 'bundler'
|
45
43
|
spec.add_development_dependency 'dry-monads', '~> 0.2'
|
44
|
+
spec.add_development_dependency 'rake', '~> 11.0'
|
45
|
+
spec.add_development_dependency 'rspec', '~> 3.3'
|
46
46
|
spec.add_development_dependency 'yard', '~> 0.9.5'
|
47
47
|
end
|
data/lib/dry/types.rb
CHANGED
@@ -33,7 +33,7 @@ module Dry
|
|
33
33
|
extend Dry::Core::Deprecations[:'dry-types']
|
34
34
|
include Dry::Core::Constants
|
35
35
|
|
36
|
-
TYPE_SPEC_REGEX =
|
36
|
+
TYPE_SPEC_REGEX = /(.+)<(.+)>/.freeze
|
37
37
|
|
38
38
|
# @see Dry.Types
|
39
39
|
def self.module(*namespaces, default: :nominal, **aliases)
|
@@ -45,7 +45,7 @@ module Dry
|
|
45
45
|
|
46
46
|
# @api private
|
47
47
|
def self.included(*)
|
48
|
-
raise
|
48
|
+
raise 'Import Dry.Types, not Dry::Types'
|
49
49
|
end
|
50
50
|
|
51
51
|
# Return container with registered built-in type objects
|
data/lib/dry/types/array.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/types/array/member'
|
4
|
+
require 'dry/types/array/constructor'
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module Types
|
@@ -24,6 +25,11 @@ module Dry
|
|
24
25
|
|
25
26
|
Array::Member.new(primitive, **options, member: member)
|
26
27
|
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
def constructor_type
|
31
|
+
::Dry::Types::Array::Constructor
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/types/constructor'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Types
|
7
|
+
# @api public
|
8
|
+
class Array < Nominal
|
9
|
+
# @api private
|
10
|
+
class Constructor < ::Dry::Types::Constructor
|
11
|
+
# @api private
|
12
|
+
def constructor_type
|
13
|
+
::Dry::Types::Array::Constructor
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Lax]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def lax
|
20
|
+
Lax.new(type.lax.constructor(fn, meta: meta))
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see Dry::Types::Array#of
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def of(member)
|
27
|
+
type.of(member).constructor(fn, meta: meta)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'dry/types/array/constructor'
|
4
|
+
|
3
5
|
module Dry
|
4
6
|
module Types
|
5
7
|
class Array < Nominal
|
@@ -111,6 +113,11 @@ module Dry
|
|
111
113
|
[:array, [member, meta ? self.meta : EMPTY_HASH]]
|
112
114
|
end
|
113
115
|
end
|
116
|
+
|
117
|
+
# @api private
|
118
|
+
def constructor_type
|
119
|
+
::Dry::Types::Array::Constructor
|
120
|
+
end
|
114
121
|
end
|
115
122
|
end
|
116
123
|
end
|
data/lib/dry/types/builder.rb
CHANGED
@@ -75,7 +75,7 @@ module Dry
|
|
75
75
|
' Be careful: types will return the same instance of the default'\
|
76
76
|
' value every time. Call `.freeze` when setting the default'\
|
77
77
|
' or pass `shared: true` to discard this warning.'\
|
78
|
-
"\n#{
|
78
|
+
"\n#{where}",
|
79
79
|
tag: :'dry-types'
|
80
80
|
)
|
81
81
|
end
|
@@ -108,21 +108,21 @@ module Dry
|
|
108
108
|
Types['nominal.hash'].map(key_type, value_type)
|
109
109
|
end
|
110
110
|
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
111
|
+
# Builds a constrained nominal type accepting any value that
|
112
|
+
# responds to given methods
|
113
|
+
#
|
114
|
+
# @example
|
115
|
+
# Types::Callable = Types.Interface(:call)
|
116
|
+
# Types::Contact = Types.Interface(:name, :address)
|
117
|
+
#
|
118
|
+
# @param methods [Array<String, Symbol>] Method names
|
119
|
+
#
|
120
|
+
# @return [Dry::Types::Contrained]
|
121
|
+
def Interface(*methods)
|
122
|
+
methods.reduce(Types['nominal.any']) do |type, method|
|
123
|
+
type.constrained(respond_to: method)
|
124
|
+
end
|
125
|
+
end
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
data/lib/dry/types/coercions.rb
CHANGED
@@ -36,8 +36,8 @@ module Dry
|
|
36
36
|
if input.respond_to?(:to_str)
|
37
37
|
begin
|
38
38
|
::Date.parse(input)
|
39
|
-
rescue ArgumentError, RangeError =>
|
40
|
-
CoercionError.handle(
|
39
|
+
rescue ArgumentError, RangeError => e
|
40
|
+
CoercionError.handle(e, &block)
|
41
41
|
end
|
42
42
|
elsif block_given?
|
43
43
|
yield
|
@@ -57,8 +57,8 @@ module Dry
|
|
57
57
|
if input.respond_to?(:to_str)
|
58
58
|
begin
|
59
59
|
::DateTime.parse(input)
|
60
|
-
rescue ArgumentError =>
|
61
|
-
CoercionError.handle(
|
60
|
+
rescue ArgumentError => e
|
61
|
+
CoercionError.handle(e, &block)
|
62
62
|
end
|
63
63
|
elsif block_given?
|
64
64
|
yield
|
@@ -78,8 +78,8 @@ module Dry
|
|
78
78
|
if input.respond_to?(:to_str)
|
79
79
|
begin
|
80
80
|
::Time.parse(input)
|
81
|
-
rescue ArgumentError =>
|
82
|
-
CoercionError.handle(
|
81
|
+
rescue ArgumentError => e
|
82
|
+
CoercionError.handle(e, &block)
|
83
83
|
end
|
84
84
|
elsif block_given?
|
85
85
|
yield
|
@@ -88,6 +88,19 @@ module Dry
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
+
# @param [#to_sym, Object] input
|
92
|
+
#
|
93
|
+
# @return [Symbol, Object]
|
94
|
+
#
|
95
|
+
# @raise CoercionError
|
96
|
+
#
|
97
|
+
# @api public
|
98
|
+
def to_symbol(input, &block)
|
99
|
+
input.to_sym
|
100
|
+
rescue NoMethodError => e
|
101
|
+
CoercionError.handle(e, &block)
|
102
|
+
end
|
103
|
+
|
91
104
|
private
|
92
105
|
|
93
106
|
# Checks whether String is empty
|