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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 02e8392346549c5801d50d1fb805951bea41e722
4
- data.tar.gz: 6e4873ce2f3f8f92eb1bbbfccfbe68aed67524c2
3
+ metadata.gz: 8ca173b64639db4a874bc33694d2a8df9f9e0500
4
+ data.tar.gz: 4bcf324022827e5145dc0cbcc4376a0958e5595f
5
5
  SHA512:
6
- metadata.gz: 1153d031efd2277c552a3b47e26395da775d5fa70600bc815c9f1a4658cb8200ba99c595b90c52c8128bd896bb017f2bcd1a0fcf80227bbb57118d2a1305f03d
7
- data.tar.gz: 0d6c974e7bf9fbb552d4abd95e15a51368685507e21eda31909c9b002c43652dd74c08244728242330797be64e5b196bc7f1763c91d204f6b51ad181d69f65a1
6
+ metadata.gz: 4f44642bb9ddfb9911fba8439b5dbcbfaa55bafbd47755c23f6279bc37da155c06e6100c56bdaebc1c783fdccd8e892b14f5b36b6eee9c81d21a3b0a9ebe2971
7
+ data.tar.gz: 5db7721ac8611a08167a91106ad5097db5796fb8664c3f36502ef7ac92706902b3e262bf5c1e9e4c1b20b045df9bfe87073acdd555322bda8b303e9bdb2088a6
@@ -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
- def self.to_nil(input)
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
- nil
51
- else
52
- result = input.to_i
23
+ return if empty_str?(input)
24
+
25
+ result = input.to_i
53
26
 
54
- if result === 0 && input != '0'
55
- input
56
- else
57
- result
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
- if result == 0.0 && (input != '0' || input != '0.0')
69
- input
70
- else
71
- result
72
- end
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
- if input == ''
78
- nil
79
- else
80
- result = to_float(input)
47
+ result = to_float(input)
81
48
 
82
- if result.is_a?(Float)
83
- result.to_d
84
- else
85
- result
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
@@ -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) }
@@ -65,4 +65,6 @@ module Dry
65
65
  end
66
66
  end
67
67
 
68
+ require 'dry/types/coercions'
68
69
  require 'dry/types/form'
70
+ require 'dry/types/json'
@@ -39,12 +39,10 @@ module Dry
39
39
  alias_method :[], :call
40
40
 
41
41
  def try(input, &block)
42
- output = call(input)
43
-
44
- if valid?(output)
45
- success(output)
42
+ if valid?(input)
43
+ success(input)
46
44
  else
47
- failure = failure(output, "#{output.inspect} must be an instance of #{primitive}")
45
+ failure = failure(input, "#{input.inspect} must be an instance of #{primitive}")
48
46
  block ? yield(failure) : failure
49
47
  end
50
48
  end
@@ -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
@@ -14,7 +14,7 @@ module Dry
14
14
 
15
15
  def default(value)
16
16
  if value.nil?
17
- raise ArgumentError, "nil cannot be used as a default of an optional type"
17
+ raise ArgumentError, "nil cannot be used as a default of a maybe type"
18
18
  else
19
19
  super
20
20
  end
@@ -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(*(new_schema.keys - prev_schema.keys))
35
- equalizer.instance_variable_get('@keys').concat(schema.keys).uniq!
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.constructor_type(type = :strict)
41
- @constructor_type ||= type
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.is_a?(self)
66
+ if attributes.instance_of?(self)
51
67
  attributes
52
68
  else
53
69
  super(constructor[attributes])
54
70
  end
55
- rescue SchemaError, SchemaKeyError => e
56
- raise StructError, "[#{self}.new] #{e.message}"
71
+ rescue SchemaError, SchemaKeyError => error
72
+ raise StructError, "[#{self}.new] #{error}"
57
73
  end
58
74
 
59
75
  def initialize(attributes)
@@ -3,7 +3,7 @@ require 'dry/types/struct'
3
3
  module Dry
4
4
  module Types
5
5
  class Value < Struct
6
- def self.new(*, &_block)
6
+ def self.new(*)
7
7
  super.freeze
8
8
  end
9
9
  end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Types
3
- VERSION = '0.7.0'.freeze
3
+ VERSION = '0.7.1'.freeze
4
4
  end
5
5
  end
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.0
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-03-30 00:00:00.000000000 Z
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