dry-types 0.9.2 → 0.9.3

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.
@@ -3,6 +3,11 @@ require 'dry/types/hash/schema'
3
3
  module Dry
4
4
  module Types
5
5
  class Hash < Definition
6
+ # @param [{Symbol => Definition}] type_map
7
+ # @param [Class] klass
8
+ # {Schema} or one of its subclasses ({Weak}, {Permissive}, {Strict},
9
+ # {StrictWithDefaults}, {Symbolized})
10
+ # @return [Schema]
6
11
  def schema(type_map, klass = Schema)
7
12
  member_types = type_map.each_with_object({}) { |(name, type), result|
8
13
  result[name] =
@@ -15,28 +20,41 @@ module Dry
15
20
  klass.new(primitive, options.merge(member_types: member_types))
16
21
  end
17
22
 
23
+ # @param [{Symbol => Definition}] type_map
24
+ # @return [Weak]
18
25
  def weak(type_map)
19
26
  schema(type_map, Weak)
20
27
  end
21
28
 
29
+ # @param [{Symbol => Definition}] type_map
30
+ # @return [Permissive]
22
31
  def permissive(type_map)
23
32
  schema(type_map, Permissive)
24
33
  end
25
34
 
35
+ # @param [{Symbol => Definition}] type_map
36
+ # @return [Strict]
26
37
  def strict(type_map)
27
38
  schema(type_map, Strict)
28
39
  end
29
40
 
41
+ # @param [{Symbol => Definition}] type_map
42
+ # @return [StrictWithDefaults]
30
43
  def strict_with_defaults(type_map)
31
44
  schema(type_map, StrictWithDefaults)
32
45
  end
33
46
 
47
+ # @param [{Symbol => Definition}] type_map
48
+ # @return [Symbolized]
34
49
  def symbolized(type_map)
35
50
  schema(type_map, Symbolized)
36
51
  end
37
52
 
38
53
  private
39
54
 
55
+ # @param [Hash] _result
56
+ # @param [Symbol] _key
57
+ # @param [Definition] _type
40
58
  def resolve_missing_value(_result, _key, _type)
41
59
  # noop
42
60
  end
@@ -1,19 +1,38 @@
1
1
  module Dry
2
2
  module Types
3
3
  class Hash < Definition
4
+ # The built-in Hash type has constructors that you can use to define
5
+ # hashes with explicit schemas and coercible values using the built-in types.
6
+ #
7
+ # Basic {Schema} evaluates default values for keys missing in input hash
8
+ # (see {Schema#resolve_missing_value})
9
+ #
10
+ # @see Dry::Types::Default#evaluate
11
+ # @see Dry::Types::Default::Callable#evaluate
4
12
  class Schema < Hash
13
+ # @return [Hash{Symbol => Definition}]
5
14
  attr_reader :member_types
6
15
 
16
+ # @param [Class] _primitive
17
+ # @param [Hash] options
18
+ # @option options [Hash{Symbol => Definition}] :member_types
7
19
  def initialize(_primitive, options)
8
20
  @member_types = options.fetch(:member_types)
9
21
  super
10
22
  end
11
23
 
24
+ # @param [Hash] hash
25
+ # @return [Hash{Symbol => Object}]
12
26
  def call(hash)
13
27
  coerce(hash)
14
28
  end
15
29
  alias_method :[], :call
16
30
 
31
+ # @param [Hash] hash
32
+ # @param [#call] block
33
+ # @yieldparam [Failure] failure
34
+ # @yieldreturn [Result]
35
+ # @return [Result]
17
36
  def try(hash, &block)
18
37
  success = true
19
38
  output = {}
@@ -40,12 +59,16 @@ module Dry
40
59
 
41
60
  private
42
61
 
62
+ # @param [Hash] hash
63
+ # @return [Hash{Symbol => Object}]
43
64
  def try_coerce(hash)
44
65
  resolve(hash) do |type, key, value|
45
66
  yield(key, type.try(value))
46
67
  end
47
68
  end
48
69
 
70
+ # @param [Hash] hash
71
+ # @return [Hash{Symbol => Object}]
49
72
  def coerce(hash)
50
73
  resolve(hash) do |type, key, value|
51
74
  begin
@@ -56,6 +79,8 @@ module Dry
56
79
  end
57
80
  end
58
81
 
82
+ # @param [Hash] hash
83
+ # @return [Hash{Symbol => Object}]
59
84
  def resolve(hash)
60
85
  result = {}
61
86
  member_types.each do |key, type|
@@ -68,6 +93,12 @@ module Dry
68
93
  result
69
94
  end
70
95
 
96
+ # @param [Hash] result
97
+ # @param [Symbol] key
98
+ # @param [Definition] type
99
+ # @return [Object]
100
+ # @see Dry::Types::Default#evaluate
101
+ # @see Dry::Types::Default::Callable#evaluate
71
102
  def resolve_missing_value(result, key, type)
72
103
  if type.default?
73
104
  result[key] = type.evaluate
@@ -77,17 +108,33 @@ module Dry
77
108
  end
78
109
  end
79
110
 
111
+ # Permissive schema raises a {MissingKeyError} if the given key is missing
112
+ # in provided hash.
80
113
  class Permissive < Schema
81
114
  private
82
115
 
116
+ # @param [Symbol] key
117
+ # @raise [MissingKeyError] when key is missing in given input
83
118
  def resolve_missing_value(_, key, _)
84
119
  raise MissingKeyError, key
85
120
  end
86
121
  end
87
122
 
123
+ # Strict hash will raise errors when keys are missing or value types are incorrect.
124
+ # Strict schema raises a {UnknownKeysError} if there are any unexpected
125
+ # keys in given hash, and raises a {MissingKeyError} if any key is missing
126
+ # in it.
127
+ # @example
128
+ # hash = Types::Hash.strict(name: Types::String, age: Types::Coercible::Int)
129
+ # hash[email: 'jane@doe.org', name: 'Jane', age: 21]
130
+ # # => Dry::Types::SchemaKeyError: :email is missing in Hash input
88
131
  class Strict < Permissive
89
132
  private
90
133
 
134
+ # @param [Hash] hash
135
+ # @return [Hash{Symbol => Object}]
136
+ # @raise [UnknownKeysError]
137
+ # if there any unexpected key in given hash
91
138
  def resolve(hash)
92
139
  unexpected = hash.keys - member_types.keys
93
140
  raise UnknownKeysError.new(*unexpected) unless unexpected.empty?
@@ -100,9 +147,20 @@ module Dry
100
147
  end
101
148
  end
102
149
 
150
+ # {StrictWithDefaults} checks that there are no extra keys
151
+ # (raises {UnknownKeysError} otherwise) and there a no missing keys
152
+ # without default values given (raises {MissingKeyError} otherwise).
153
+ # @see Default#evaluate
154
+ # @see Default::Callable#evaluate
103
155
  class StrictWithDefaults < Strict
104
156
  private
105
157
 
158
+ # @param [Hash] result
159
+ # @param [Symbol] key
160
+ # @param [Definition] type
161
+ # @return [Object]
162
+ # @see Dry::Types::Default#evaluate
163
+ # @see Dry::Types::Default::Callable#evaluate
106
164
  def resolve_missing_value(result, key, type)
107
165
  if type.default?
108
166
  result[key] = type.evaluate
@@ -112,7 +170,12 @@ module Dry
112
170
  end
113
171
  end
114
172
 
173
+ # Weak schema provides safe types for every type given in schema hash
174
+ # @see Safe
115
175
  class Weak < Schema
176
+ # @param [Class] primitive
177
+ # @param [Hash] options
178
+ # @see #initialize
116
179
  def self.new(primitive, options)
117
180
  member_types = options.
118
181
  fetch(:member_types).
@@ -121,6 +184,11 @@ module Dry
121
184
  super(primitive, options.merge(member_types: member_types))
122
185
  end
123
186
 
187
+ # @param [Hash] hash
188
+ # @param [#call] block
189
+ # @yieldparam [Failure] failure
190
+ # @yieldreturn [Result]
191
+ # @return [Result]
124
192
  def try(hash, &block)
125
193
  if hash.is_a?(::Hash)
126
194
  super
@@ -131,6 +199,7 @@ module Dry
131
199
  end
132
200
  end
133
201
 
202
+ # {Symbolized} hash will turn string key names into symbols.
134
203
  class Symbolized < Weak
135
204
  private
136
205
 
@@ -1,18 +1,24 @@
1
1
  module Dry
2
2
  module Types
3
3
  module Options
4
+ # @return [Hash]
4
5
  attr_reader :options
5
6
 
7
+ # @see Definition#initialize
6
8
  def initialize(*args, **options)
7
9
  @__args__ = args
8
10
  @options = options
9
11
  @meta = options.fetch(:meta, {})
10
12
  end
11
13
 
14
+ # @param [Hash] new_options
15
+ # @return [Definition]
12
16
  def with(new_options)
13
17
  self.class.new(*@__args__, options.merge(new_options))
14
18
  end
15
19
 
20
+ # @param [Hash] data
21
+ # @return [Hash, Definition]
16
22
  def meta(data = nil)
17
23
  data ? with(meta: @meta.merge(data)) : @meta
18
24
  end
@@ -5,17 +5,21 @@ module Dry
5
5
  class Result
6
6
  include Dry::Equalizer(:input)
7
7
 
8
+ # @return [Object]
8
9
  attr_reader :input
9
10
 
11
+ # @param [Object] input
10
12
  def initialize(input)
11
13
  @input = input
12
14
  end
13
15
 
14
16
  class Success < Result
17
+ # @return [true]
15
18
  def success?
16
19
  true
17
20
  end
18
21
 
22
+ # @return [false]
19
23
  def failure?
20
24
  false
21
25
  end
@@ -24,21 +28,27 @@ module Dry
24
28
  class Failure < Result
25
29
  include Dry::Equalizer(:input, :error)
26
30
 
31
+ # @return [#to_s]
27
32
  attr_reader :error
28
33
 
34
+ # @param [Object] input
35
+ # @param [#to_s] error
29
36
  def initialize(input, error)
30
37
  super(input)
31
38
  @error = error
32
39
  end
33
40
 
41
+ # @return [String]
34
42
  def to_s
35
43
  error.to_s
36
44
  end
37
45
 
46
+ # @return [false]
38
47
  def success?
39
48
  false
40
49
  end
41
50
 
51
+ # @return [true]
42
52
  def failure?
43
53
  true
44
54
  end
@@ -7,6 +7,8 @@ module Dry
7
7
  include Decorator
8
8
  include Builder
9
9
 
10
+ # @param [Object] input
11
+ # @return [Object]
10
12
  def call(input)
11
13
  result = try(input)
12
14
 
@@ -18,6 +20,11 @@ module Dry
18
20
  end
19
21
  alias_method :[], :call
20
22
 
23
+ # @param [Object] input
24
+ # @param [#call] block
25
+ # @yieldparam [Failure] failure
26
+ # @yieldreturn [Result]
27
+ # @return [Result]
21
28
  def try(input, &block)
22
29
  type.try(input, &block)
23
30
  rescue TypeError, ArgumentError => e
@@ -27,6 +34,8 @@ module Dry
27
34
 
28
35
  private
29
36
 
37
+ # @param [Object, Dry::Types::Constructor] response
38
+ # @return [Boolean]
30
39
  def decorate?(response)
31
40
  super || response.kind_of?(Constructor)
32
41
  end
data/lib/dry/types/sum.rb CHANGED
@@ -7,19 +7,26 @@ module Dry
7
7
  include Builder
8
8
  include Options
9
9
 
10
+ # @return [Definition]
10
11
  attr_reader :left
11
12
 
13
+ # @return [Definition]
12
14
  attr_reader :right
13
15
 
14
16
  class Constrained < Sum
17
+ # @return [Dry::Logic::Rule]
15
18
  def rule
16
19
  left.rule | right.rule
17
20
  end
18
21
 
22
+ # @return [true]
19
23
  def constrained?
20
24
  true
21
25
  end
22
26
 
27
+ # @param [Object] input
28
+ # @return [Object]
29
+ # @raise [ConstraintError] if given +input+ not passing {#try}
23
30
  def call(input)
24
31
  try(input) do |result|
25
32
  raise ConstraintError.new(result, input)
@@ -28,28 +35,37 @@ module Dry
28
35
  alias_method :[], :call
29
36
  end
30
37
 
38
+ # @param [Definition] left
39
+ # @param [Definition] right
40
+ # @param [Hash] options
31
41
  def initialize(left, right, options = {})
32
42
  super
33
43
  @left, @right = left, right
34
44
  freeze
35
45
  end
36
46
 
47
+ # @return [String]
37
48
  def name
38
49
  [left, right].map(&:name).join(' | ')
39
50
  end
40
51
 
52
+ # @return [false]
41
53
  def default?
42
54
  false
43
55
  end
44
56
 
57
+ # @return [false]
45
58
  def maybe?
46
59
  false
47
60
  end
48
61
 
62
+ # @return [false]
49
63
  def constrained?
50
64
  false
51
65
  end
52
66
 
67
+ # @param [Object] input
68
+ # @return [Object]
53
69
  def call(input)
54
70
  try(input).input
55
71
  end
@@ -69,10 +85,14 @@ module Dry
69
85
  end
70
86
  end
71
87
 
88
+ # @param [Object] value
89
+ # @return [Boolean]
72
90
  def primitive?(value)
73
91
  left.primitive?(value) || right.primitive?(value)
74
92
  end
75
93
 
94
+ # @param [Object] value
95
+ # @return [Boolean]
76
96
  def valid?(value)
77
97
  left.valid?(value) || right.valid?(value)
78
98
  end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Types
3
- VERSION = '0.9.2'.freeze
3
+ VERSION = '0.9.3'.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.9.2
4
+ version: 0.9.3
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-13 00:00:00.000000000 Z
11
+ date: 2016-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -31,6 +31,9 @@ dependencies:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0.2'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.2.1
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +41,9 @@ dependencies:
38
41
  - - "~>"
39
42
  - !ruby/object:Gem::Version
40
43
  version: '0.2'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.2.1
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: dry-container
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -176,6 +182,20 @@ dependencies:
176
182
  - - "~>"
177
183
  - !ruby/object:Gem::Version
178
184
  version: '0.2'
185
+ - !ruby/object:Gem::Dependency
186
+ name: yard
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - "~>"
190
+ - !ruby/object:Gem::Version
191
+ version: 0.9.5
192
+ type: :development
193
+ prerelease: false
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - "~>"
197
+ - !ruby/object:Gem::Version
198
+ version: 0.9.5
179
199
  description: Type system for Ruby supporting coercions, constraints and complex types
180
200
  like structs, value objects, enums etc.
181
201
  email:
@@ -187,6 +207,7 @@ files:
187
207
  - ".gitignore"
188
208
  - ".rspec"
189
209
  - ".travis.yml"
210
+ - ".yardopts"
190
211
  - CHANGELOG.md
191
212
  - Gemfile
192
213
  - LICENSE