dry-types 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/dry/types/coercions.rb +35 -0
- data/lib/dry/types/coercions/form.rb +20 -54
- data/lib/dry/types/coercions/json.rb +18 -0
- data/lib/dry/types/compiler.rb +13 -0
- data/lib/dry/types/core.rb +2 -0
- data/lib/dry/types/definition.rb +3 -5
- data/lib/dry/types/errors.rb +6 -0
- data/lib/dry/types/json.rb +33 -0
- data/lib/dry/types/maybe.rb +1 -1
- data/lib/dry/types/struct.rb +24 -8
- data/lib/dry/types/value.rb +1 -1
- data/lib/dry/types/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ca173b64639db4a874bc33694d2a8df9f9e0500
|
4
|
+
data.tar.gz: 4bcf324022827e5145dc0cbcc4376a0958e5595f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f44642bb9ddfb9911fba8439b5dbcbfaa55bafbd47755c23f6279bc37da155c06e6100c56bdaebc1c783fdccd8e892b14f5b36b6eee9c81d21a3b0a9ebe2971
|
7
|
+
data.tar.gz: 5db7721ac8611a08167a91106ad5097db5796fb8664c3f36502ef7ac92706902b3e262bf5c1e9e4c1b20b045df9bfe87073acdd555322bda8b303e9bdb2088a6
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# v0.7.1 2016-04-06
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
- `JSON::*` types with JSON-specific coercions (coop)
|
6
|
+
|
7
|
+
## Fixed
|
8
|
+
|
9
|
+
- Schema is properly inherited in Struct (backus)
|
10
|
+
- `constructor_type` is properly inherited in Struct (fbernier)
|
11
|
+
|
12
|
+
[Compare v0.7.0...v0.7.1](https://github.com/dryrb/dry-types/compare/v0.7.0...v0.7.1)
|
13
|
+
|
1
14
|
# v0.7.0 2016-03-30
|
2
15
|
|
3
16
|
Major focus of this release is to make complex type composition possible and improving constraint errors to be more meaningful.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Dry
|
2
|
+
module Types
|
3
|
+
module Coercions
|
4
|
+
EMPTY_STRING = ''.freeze
|
5
|
+
|
6
|
+
def to_nil(input)
|
7
|
+
input unless empty_str?(input)
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_date(input)
|
11
|
+
Date.parse(input)
|
12
|
+
rescue ArgumentError
|
13
|
+
input
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_date_time(input)
|
17
|
+
DateTime.parse(input)
|
18
|
+
rescue ArgumentError
|
19
|
+
input
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_time(input)
|
23
|
+
Time.parse(input)
|
24
|
+
rescue ArgumentError
|
25
|
+
input
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def empty_str?(value)
|
31
|
+
EMPTY_STRING.eql?(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
|
-
require 'date'
|
2
1
|
require 'bigdecimal'
|
3
2
|
require 'bigdecimal/util'
|
4
|
-
require 'time'
|
5
3
|
|
6
4
|
module Dry
|
7
5
|
module Types
|
@@ -11,31 +9,7 @@ module Dry
|
|
11
9
|
FALSE_VALUES = %w[0 off f false n no].freeze
|
12
10
|
BOOLEAN_MAP = ::Hash[TRUE_VALUES.product([true]) + FALSE_VALUES.product([false])].freeze
|
13
11
|
|
14
|
-
|
15
|
-
if input.is_a?(String) && input == ''
|
16
|
-
nil
|
17
|
-
else
|
18
|
-
input
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.to_date(input)
|
23
|
-
Date.parse(input)
|
24
|
-
rescue ArgumentError
|
25
|
-
input
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.to_date_time(input)
|
29
|
-
DateTime.parse(input)
|
30
|
-
rescue ArgumentError
|
31
|
-
input
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.to_time(input)
|
35
|
-
Time.parse(input)
|
36
|
-
rescue ArgumentError
|
37
|
-
input
|
38
|
-
end
|
12
|
+
extend Coercions
|
39
13
|
|
40
14
|
def self.to_true(input)
|
41
15
|
BOOLEAN_MAP.fetch(input, input)
|
@@ -46,44 +20,36 @@ module Dry
|
|
46
20
|
end
|
47
21
|
|
48
22
|
def self.to_int(input)
|
49
|
-
if input
|
50
|
-
|
51
|
-
|
52
|
-
result = input.to_i
|
23
|
+
return if empty_str?(input)
|
24
|
+
|
25
|
+
result = input.to_i
|
53
26
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
27
|
+
if result === 0 && !input.eql?('0')
|
28
|
+
input
|
29
|
+
else
|
30
|
+
result
|
59
31
|
end
|
60
32
|
end
|
61
33
|
|
62
34
|
def self.to_float(input)
|
63
|
-
if input
|
64
|
-
nil
|
65
|
-
else
|
66
|
-
result = input.to_f
|
35
|
+
return if empty_str?(input)
|
67
36
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
37
|
+
result = input.to_f
|
38
|
+
|
39
|
+
if result.eql?(0.0) && (!input.eql?('0') && !input.eql?('0.0'))
|
40
|
+
input
|
41
|
+
else
|
42
|
+
result
|
73
43
|
end
|
74
44
|
end
|
75
45
|
|
76
46
|
def self.to_decimal(input)
|
77
|
-
|
78
|
-
nil
|
79
|
-
else
|
80
|
-
result = to_float(input)
|
47
|
+
result = to_float(input)
|
81
48
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
49
|
+
if result.instance_of?(Float)
|
50
|
+
result.to_d
|
51
|
+
else
|
52
|
+
result
|
87
53
|
end
|
88
54
|
end
|
89
55
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'bigdecimal/util'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
module Dry
|
7
|
+
module Types
|
8
|
+
module Coercions
|
9
|
+
module JSON
|
10
|
+
extend Coercions
|
11
|
+
|
12
|
+
def self.to_decimal(input)
|
13
|
+
input.to_d unless empty_str?(input)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/dry/types/compiler.rb
CHANGED
@@ -43,6 +43,10 @@ module Dry
|
|
43
43
|
registry['form.array'].member(call(node))
|
44
44
|
end
|
45
45
|
|
46
|
+
def visit_json_array(node)
|
47
|
+
registry['json.array'].member(call(node))
|
48
|
+
end
|
49
|
+
|
46
50
|
def visit_hash(node)
|
47
51
|
constructor, schema = node
|
48
52
|
merge_with('hash', constructor, schema)
|
@@ -57,6 +61,15 @@ module Dry
|
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
64
|
+
def visit_json_hash(node)
|
65
|
+
if node
|
66
|
+
constructor, schema = node
|
67
|
+
merge_with('json.hash', constructor, schema)
|
68
|
+
else
|
69
|
+
registry['json.hash']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
60
73
|
def visit_key(node)
|
61
74
|
name, types = node
|
62
75
|
{ name => visit(types) }
|
data/lib/dry/types/core.rb
CHANGED
data/lib/dry/types/definition.rb
CHANGED
@@ -39,12 +39,10 @@ module Dry
|
|
39
39
|
alias_method :[], :call
|
40
40
|
|
41
41
|
def try(input, &block)
|
42
|
-
|
43
|
-
|
44
|
-
if valid?(output)
|
45
|
-
success(output)
|
42
|
+
if valid?(input)
|
43
|
+
success(input)
|
46
44
|
else
|
47
|
-
failure = failure(
|
45
|
+
failure = failure(input, "#{input.inspect} must be an instance of #{primitive}")
|
48
46
|
block ? yield(failure) : failure
|
49
47
|
end
|
50
48
|
end
|
data/lib/dry/types/errors.rb
CHANGED
@@ -18,6 +18,12 @@ module Dry
|
|
18
18
|
|
19
19
|
StructError = Class.new(TypeError)
|
20
20
|
|
21
|
+
class RepeatedAttributeError < ArgumentError
|
22
|
+
def initialize(key)
|
23
|
+
super("Attribute :#{key} has already been defined")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
21
27
|
ConstraintError = Class.new(TypeError) do
|
22
28
|
attr_reader :result
|
23
29
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'dry/types/coercions/json'
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Types
|
5
|
+
register('json.nil') do
|
6
|
+
self['nil'].constructor(Coercions::JSON.method(:to_nil))
|
7
|
+
end
|
8
|
+
|
9
|
+
register('json.date') do
|
10
|
+
self['date'].constructor(Coercions::JSON.method(:to_date))
|
11
|
+
end
|
12
|
+
|
13
|
+
register('json.date_time') do
|
14
|
+
self['date_time'].constructor(Coercions::JSON.method(:to_date_time))
|
15
|
+
end
|
16
|
+
|
17
|
+
register('json.time') do
|
18
|
+
self['time'].constructor(Coercions::JSON.method(:to_time))
|
19
|
+
end
|
20
|
+
|
21
|
+
register('json.decimal') do
|
22
|
+
self['decimal'].constructor(Coercions::JSON.method(:to_decimal))
|
23
|
+
end
|
24
|
+
|
25
|
+
register('json.array') do
|
26
|
+
self['array'].safe
|
27
|
+
end
|
28
|
+
|
29
|
+
register('json.hash') do
|
30
|
+
self['hash'].safe
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/dry/types/maybe.rb
CHANGED
data/lib/dry/types/struct.rb
CHANGED
@@ -8,13 +8,16 @@ module Dry
|
|
8
8
|
def self.inherited(klass)
|
9
9
|
super
|
10
10
|
|
11
|
-
klass.instance_variable_set('@equalizer', Equalizer.new)
|
11
|
+
klass.instance_variable_set('@equalizer', Equalizer.new(*schema.keys))
|
12
|
+
klass.instance_variable_set('@constructor_type', constructor_type)
|
12
13
|
klass.send(:include, klass.equalizer)
|
13
14
|
|
14
15
|
unless klass == Value
|
15
16
|
klass.instance_variable_set('@constructor', Types['coercible.hash'])
|
16
17
|
Types.register_class(klass)
|
17
18
|
end
|
19
|
+
|
20
|
+
klass.attributes({}) unless equal?(Struct)
|
18
21
|
end
|
19
22
|
|
20
23
|
def self.equalizer
|
@@ -26,19 +29,32 @@ module Dry
|
|
26
29
|
end
|
27
30
|
|
28
31
|
def self.attributes(new_schema)
|
32
|
+
check_schema_duplication(new_schema)
|
33
|
+
|
29
34
|
prev_schema = schema
|
30
35
|
|
31
36
|
@schema = prev_schema.merge(new_schema)
|
32
37
|
@constructor = Types['coercible.hash'].public_send(constructor_type, schema)
|
33
38
|
|
34
|
-
attr_reader(*
|
35
|
-
equalizer.instance_variable_get('@keys').concat(
|
39
|
+
attr_reader(*new_schema.keys)
|
40
|
+
equalizer.instance_variable_get('@keys').concat(new_schema.keys)
|
36
41
|
|
37
42
|
self
|
38
43
|
end
|
39
44
|
|
40
|
-
def self.
|
41
|
-
|
45
|
+
def self.check_schema_duplication(new_schema)
|
46
|
+
shared_keys = new_schema.keys & schema.keys
|
47
|
+
|
48
|
+
fail RepeatedAttributeError, shared_keys.first if shared_keys.any?
|
49
|
+
end
|
50
|
+
private_class_method :check_schema_duplication
|
51
|
+
|
52
|
+
def self.constructor_type(type = nil)
|
53
|
+
if type
|
54
|
+
@constructor_type = type
|
55
|
+
else
|
56
|
+
@constructor_type || :strict
|
57
|
+
end
|
42
58
|
end
|
43
59
|
|
44
60
|
def self.schema
|
@@ -47,13 +63,13 @@ module Dry
|
|
47
63
|
end
|
48
64
|
|
49
65
|
def self.new(attributes = {})
|
50
|
-
if attributes.
|
66
|
+
if attributes.instance_of?(self)
|
51
67
|
attributes
|
52
68
|
else
|
53
69
|
super(constructor[attributes])
|
54
70
|
end
|
55
|
-
rescue SchemaError, SchemaKeyError =>
|
56
|
-
raise StructError, "[#{self}.new] #{
|
71
|
+
rescue SchemaError, SchemaKeyError => error
|
72
|
+
raise StructError, "[#{self}.new] #{error}"
|
57
73
|
end
|
58
74
|
|
59
75
|
def initialize(attributes)
|
data/lib/dry/types/value.rb
CHANGED
data/lib/dry/types/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-types
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -188,7 +188,9 @@ files:
|
|
188
188
|
- lib/dry/types/array.rb
|
189
189
|
- lib/dry/types/array/member.rb
|
190
190
|
- lib/dry/types/builder.rb
|
191
|
+
- lib/dry/types/coercions.rb
|
191
192
|
- lib/dry/types/coercions/form.rb
|
193
|
+
- lib/dry/types/coercions/json.rb
|
192
194
|
- lib/dry/types/compiler.rb
|
193
195
|
- lib/dry/types/constrained.rb
|
194
196
|
- lib/dry/types/constrained/coercible.rb
|
@@ -204,6 +206,7 @@ files:
|
|
204
206
|
- lib/dry/types/form.rb
|
205
207
|
- lib/dry/types/hash.rb
|
206
208
|
- lib/dry/types/hash/schema.rb
|
209
|
+
- lib/dry/types/json.rb
|
207
210
|
- lib/dry/types/maybe.rb
|
208
211
|
- lib/dry/types/options.rb
|
209
212
|
- lib/dry/types/result.rb
|