dry-data 0.3.2 → 0.4.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 +13 -0
- data/README.md +20 -2
- data/lib/dry/data.rb +15 -9
- data/lib/dry/data/optional.rb +20 -0
- data/lib/dry/data/sum_type.rb +0 -17
- data/lib/dry/data/type.rb +6 -2
- data/lib/dry/data/type/array.rb +14 -6
- data/lib/dry/data/type/constrained.rb +5 -1
- data/lib/dry/data/types.rb +2 -8
- data/lib/dry/data/version.rb +1 -1
- metadata +3 -3
- data/lib/dry/data/type/optional.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8204add8315ec4efed8923ffb753d5e670e56b3
|
4
|
+
data.tar.gz: 1a9bd0c932aa43bbdeba519cc00b5bae7ccfdfbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d0dea2a50e1b8a212c43eec8cd10ca463c53fa1cb8982db307f29fdf397c006fd7febe9c0fbabd2f146f94112f0a1bfcfdde627a94e80ce82a53548b4674876
|
7
|
+
data.tar.gz: a364d893f9d2bf9a4aba61970020ded68f136ca3bc8877a06783aa37e7ffcc0e4436acd629ad165cb1448a29460b3dd0b0290df747d1928a1228e7afbfad7646
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# v0.4.0 2015-12-11
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
* Support for sum-types with constraint type (solnic)
|
6
|
+
* `Dry::Data::Type#optional` for defining optional types (solnic)
|
7
|
+
|
8
|
+
## Changed
|
9
|
+
|
10
|
+
* `Dry::Data['optional']` was **removed** in favor of `Dry::Data::Type#optional` (solnic)
|
11
|
+
|
12
|
+
[Compare v0.3.2...v0.4.0](https://github.com/dryrb/dry-data/compare/v0.3.2...v0.4.0)
|
13
|
+
|
1
14
|
# v0.3.2 2015-12-10
|
2
15
|
|
3
16
|
## Added
|
data/README.md
CHANGED
@@ -146,7 +146,7 @@ maybe_int['12.3'] # Some(12.3)
|
|
146
146
|
You can define your own optional types too:
|
147
147
|
|
148
148
|
``` ruby
|
149
|
-
maybe_string = Dry::Data["
|
149
|
+
maybe_string = Dry::Data["string"].optional
|
150
150
|
|
151
151
|
maybe_string[nil]
|
152
152
|
# => None
|
@@ -164,6 +164,24 @@ maybe_string['something'].fmap(&:upcase).value
|
|
164
164
|
# => "SOMETHING"
|
165
165
|
```
|
166
166
|
|
167
|
+
### Sum-types
|
168
|
+
|
169
|
+
You can specify sum types using `|` operator, it is an explicit way of defining
|
170
|
+
what are the valid types of a value.
|
171
|
+
|
172
|
+
In example `dry-data` defines `bool` type which is a sum-type consisting of `true`
|
173
|
+
and `false` types which is expressed as `Dry::Data['true'] | Dry::Data['false']`
|
174
|
+
(and it has its strict version, too).
|
175
|
+
|
176
|
+
Another common case is defining that something can be either `nil` or something else:
|
177
|
+
|
178
|
+
``` ruby
|
179
|
+
nil_or_string = Dry::Data['strict.nil'] | Dry::Data['strict.string']
|
180
|
+
|
181
|
+
nil_or_string[nil] # => nil
|
182
|
+
nil_or_string["hello"] # => "hello"
|
183
|
+
```
|
184
|
+
|
167
185
|
### Constrained Types
|
168
186
|
|
169
187
|
You can create constrained types that will use validation rules to check if the
|
@@ -173,7 +191,7 @@ a lower level guarantee that you're not instantiating objects that are broken.
|
|
173
191
|
All types support constraints API, but not all constraints are suitable for a
|
174
192
|
particular primitive, it's up to you to set up constraints that make sense.
|
175
193
|
|
176
|
-
Under the hood it uses `dry-validation`
|
194
|
+
Under the hood it uses [`dry-validation`](https://github.com/dryrb/dry-validation)
|
177
195
|
and all of its predicates are supported.
|
178
196
|
|
179
197
|
IMPORTANT: `dry-data` does not have a runtime dependency on `dry-validation` so
|
data/lib/dry/data.rb
CHANGED
@@ -3,7 +3,7 @@ require 'date'
|
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
require 'inflecto'
|
6
|
-
require 'thread_safe
|
6
|
+
require 'thread_safe'
|
7
7
|
|
8
8
|
require 'dry-container'
|
9
9
|
require 'dry-equalizer'
|
@@ -59,17 +59,23 @@ module Dry
|
|
59
59
|
|
60
60
|
def self.[](name)
|
61
61
|
type_map.fetch_or_store(name) do
|
62
|
-
result = name.match(TYPE_SPEC_REGEX)
|
63
|
-
|
64
62
|
type =
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
63
|
+
case name
|
64
|
+
when String
|
65
|
+
result = name.match(TYPE_SPEC_REGEX)
|
66
|
+
|
67
|
+
type =
|
68
|
+
if result
|
69
|
+
type_id, member_id = result[1..2]
|
70
|
+
container[type_id].member(self[member_id])
|
71
|
+
else
|
72
|
+
container[name]
|
73
|
+
end
|
74
|
+
when Class
|
75
|
+
self[identifier(name)]
|
70
76
|
end
|
71
77
|
|
72
|
-
|
78
|
+
type
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dry
|
2
|
+
module Data
|
3
|
+
class Optional
|
4
|
+
attr_reader :type
|
5
|
+
|
6
|
+
def initialize(type)
|
7
|
+
@type = type
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid?(input)
|
11
|
+
type.valid?(input)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(input)
|
15
|
+
Maybe(type[input])
|
16
|
+
end
|
17
|
+
alias_method :[], :call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/dry/data/sum_type.rb
CHANGED
@@ -2,28 +2,11 @@ require 'kleisli'
|
|
2
2
|
|
3
3
|
module Dry
|
4
4
|
module Data
|
5
|
-
def self.SumType(left, right)
|
6
|
-
klass =
|
7
|
-
if left.is_a?(Type::Optional)
|
8
|
-
SumType::Optional
|
9
|
-
else
|
10
|
-
SumType
|
11
|
-
end
|
12
|
-
klass.new(left, right)
|
13
|
-
end
|
14
|
-
|
15
5
|
class SumType
|
16
6
|
attr_reader :left
|
17
7
|
|
18
8
|
attr_reader :right
|
19
9
|
|
20
|
-
class Optional < SumType
|
21
|
-
def call(input)
|
22
|
-
Maybe(super(input))
|
23
|
-
end
|
24
|
-
alias_method :[], :call
|
25
|
-
end
|
26
|
-
|
27
10
|
def initialize(left, right)
|
28
11
|
@left, @right = left, right
|
29
12
|
end
|
data/lib/dry/data/type.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'dry/data/type/optional'
|
2
1
|
require 'dry/data/type/hash'
|
3
2
|
require 'dry/data/type/array'
|
4
3
|
require 'dry/data/type/enum'
|
5
4
|
|
6
5
|
require 'dry/data/sum_type'
|
6
|
+
require 'dry/data/optional'
|
7
7
|
|
8
8
|
module Dry
|
9
9
|
module Data
|
@@ -62,6 +62,10 @@ module Dry
|
|
62
62
|
Enum.new(values, constrained(inclusion: values))
|
63
63
|
end
|
64
64
|
|
65
|
+
def optional
|
66
|
+
Optional.new(Data['nil'] | self)
|
67
|
+
end
|
68
|
+
|
65
69
|
def name
|
66
70
|
primitive.name
|
67
71
|
end
|
@@ -76,7 +80,7 @@ module Dry
|
|
76
80
|
end
|
77
81
|
|
78
82
|
def |(other)
|
79
|
-
|
83
|
+
SumType.new(self, other)
|
80
84
|
end
|
81
85
|
end
|
82
86
|
end
|
data/lib/dry/data/type/array.rb
CHANGED
@@ -2,15 +2,23 @@ module Dry
|
|
2
2
|
module Data
|
3
3
|
class Type
|
4
4
|
class Array < Type
|
5
|
-
def self.constructor(array_constructor,
|
6
|
-
array_constructor[input].map(&
|
5
|
+
def self.constructor(array_constructor, member_constructor, input)
|
6
|
+
array_constructor[input].map(&member_constructor)
|
7
7
|
end
|
8
8
|
|
9
9
|
def member(type)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
member_constructor =
|
11
|
+
case type
|
12
|
+
when Type then type.constructor
|
13
|
+
when Class then Data[type].constructor
|
14
|
+
else
|
15
|
+
raise ArgumentError, "+#{type}+ is an unsupported array member"
|
16
|
+
end
|
17
|
+
|
18
|
+
array_constructor = self.class
|
19
|
+
.method(:constructor).to_proc.curry.(constructor, member_constructor)
|
20
|
+
|
21
|
+
self.class.new(array_constructor, primitive)
|
14
22
|
end
|
15
23
|
end
|
16
24
|
end
|
@@ -14,13 +14,17 @@ module Dry
|
|
14
14
|
def call(input)
|
15
15
|
result = super(input)
|
16
16
|
|
17
|
-
if
|
17
|
+
if valid?(result)
|
18
18
|
result
|
19
19
|
else
|
20
20
|
raise ConstraintError, "#{input.inspect} violates constraints"
|
21
21
|
end
|
22
22
|
end
|
23
23
|
alias_method :[], :call
|
24
|
+
|
25
|
+
def valid?(input)
|
26
|
+
super && rule.(input).success?
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
def constrained(options)
|
data/lib/dry/data/types.rb
CHANGED
@@ -22,12 +22,6 @@ module Dry
|
|
22
22
|
|
23
23
|
ALL_PRIMITIVES = COERCIBLE.merge(NON_COERCIBLE).freeze
|
24
24
|
|
25
|
-
# Register optional type
|
26
|
-
register(
|
27
|
-
'optional',
|
28
|
-
Type::Optional.new(Type.method(:passthrough_constructor), NilClass)
|
29
|
-
)
|
30
|
-
|
31
25
|
# Register built-in primitive types with kernel coercion methods
|
32
26
|
COERCIBLE.each do |name, primitive|
|
33
27
|
register(
|
@@ -55,12 +49,12 @@ module Dry
|
|
55
49
|
# Register non-coercible maybe types
|
56
50
|
ALL_PRIMITIVES.each do |name, primitive|
|
57
51
|
next if name == :nil
|
58
|
-
register("maybe.strict.#{name}", self["
|
52
|
+
register("maybe.strict.#{name}", self["strict.#{name}"].optional)
|
59
53
|
end
|
60
54
|
|
61
55
|
# Register coercible maybe types
|
62
56
|
COERCIBLE.each do |name, primitive|
|
63
|
-
register("maybe.coercible.#{name}", self["
|
57
|
+
register("maybe.coercible.#{name}", self["coercible.#{name}"].optional)
|
64
58
|
end
|
65
59
|
|
66
60
|
# Register :bool since it's common and not a built-in Ruby type :(
|
data/lib/dry/data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thread_safe
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- lib/dry/data/constraints.rb
|
170
170
|
- lib/dry/data/container.rb
|
171
171
|
- lib/dry/data/dsl.rb
|
172
|
+
- lib/dry/data/optional.rb
|
172
173
|
- lib/dry/data/struct.rb
|
173
174
|
- lib/dry/data/sum_type.rb
|
174
175
|
- lib/dry/data/type.rb
|
@@ -176,7 +177,6 @@ files:
|
|
176
177
|
- lib/dry/data/type/constrained.rb
|
177
178
|
- lib/dry/data/type/enum.rb
|
178
179
|
- lib/dry/data/type/hash.rb
|
179
|
-
- lib/dry/data/type/optional.rb
|
180
180
|
- lib/dry/data/types.rb
|
181
181
|
- lib/dry/data/types/form.rb
|
182
182
|
- lib/dry/data/value.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Data
|
3
|
-
class Type
|
4
|
-
class Optional < Type
|
5
|
-
def |(other)
|
6
|
-
Data.SumType(self.class.new(constructor, other.primitive), other)
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(input)
|
10
|
-
Maybe(input)
|
11
|
-
end
|
12
|
-
|
13
|
-
def valid?(input)
|
14
|
-
input.nil? || super
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|