dry-types 0.7.0 → 0.7.1
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/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
|