dry-types 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,11 @@ module Dry
2
2
  module Types
3
3
  class Constrained
4
4
  class Coercible < Constrained
5
+ # @param [Object] input
6
+ # @param [#call] block
7
+ # @yieldparam [Failure] failure
8
+ # @yieldreturn [Result]
9
+ # @return [Result]
5
10
  def try(input, &block)
6
11
  result = type.try(input)
7
12
 
@@ -4,12 +4,15 @@ require 'dry/logic/rule/predicate'
4
4
 
5
5
  module Dry
6
6
  module Types
7
+ # @param [Hash] options
8
+ # @return [Dry::Logic::Rule]
7
9
  def self.Rule(options)
8
10
  rule_compiler.(
9
11
  options.map { |key, val| Logic::Rule::Predicate.new(Logic::Predicates[:"#{key}?"]).curry(val).to_ast }
10
12
  ).reduce(:and)
11
13
  end
12
14
 
15
+ # @return [Dry::Logic::RuleCompiler]
13
16
  def self.rule_compiler
14
17
  @rule_compiler ||= Logic::RuleCompiler.new(Logic::Predicates)
15
18
  end
@@ -5,36 +5,54 @@ module Dry
5
5
  class Constructor < Definition
6
6
  include Dry::Equalizer(:type)
7
7
 
8
+ # @return [#call]
8
9
  attr_reader :fn
9
10
 
11
+ # @return [Definition]
10
12
  attr_reader :type
11
13
 
14
+ # @param [Builder, Object] input
15
+ # @param [Hash] options
16
+ # @param [#call] block
12
17
  def self.new(input, options = {}, &block)
13
18
  type = input.is_a?(Builder) ? input : Definition.new(input)
14
19
  super(type, options, &block)
15
20
  end
16
21
 
22
+ # @param [Definition] type
23
+ # @param [Hash] options
24
+ # @param [#proc] block
17
25
  def initialize(type, options = {}, &block)
18
26
  @type = type
19
27
  @fn = options.fetch(:fn, block)
20
28
  super
21
29
  end
22
30
 
31
+ # @return [Class]
23
32
  def primitive
24
33
  type.primitive
25
34
  end
26
35
 
36
+ # @param [Object] input
37
+ # @return [Object]
27
38
  def call(input)
28
39
  type[fn[input]]
29
40
  end
30
41
  alias_method :[], :call
31
42
 
43
+ # @param [Object] input
44
+ # @param [#call] block
45
+ # @return [Result]
32
46
  def try(input, &block)
33
47
  type.try(fn[input], &block)
34
48
  rescue TypeError => e
35
49
  failure(input, e.message)
36
50
  end
37
51
 
52
+ # @param [#call, nil] new_fn
53
+ # @param [Hash] options
54
+ # @param [#call] block
55
+ # @return [Constructor]
38
56
  def constructor(new_fn = nil, **options, &block)
39
57
  left = new_fn || block
40
58
  right = fn
@@ -42,20 +60,30 @@ module Dry
42
60
  with(options.merge(fn: -> input { left[right[input]] }))
43
61
  end
44
62
 
63
+ # @param [Object] value
64
+ # @return [Boolean]
45
65
  def valid?(value)
46
66
  super && type.valid?(value)
47
67
  end
48
68
 
69
+ # @return [Class]
49
70
  def constrained_type
50
71
  Constrained::Coercible
51
72
  end
52
73
 
53
74
  private
54
75
 
76
+ # @param [Symbol] meth
77
+ # @param [Boolean] include_private
78
+ # @return [Boolean]
55
79
  def respond_to_missing?(meth, include_private = false)
56
80
  super || type.respond_to?(meth)
57
81
  end
58
82
 
83
+ # Delegates missing methods to {#type}
84
+ # @param [Symbol] meth
85
+ # @param [Array] args
86
+ # @param [#call] block
59
87
  def method_missing(meth, *args, &block)
60
88
  if type.respond_to?(meth)
61
89
  response = type.__send__(meth, *args, &block)
@@ -5,43 +5,62 @@ module Dry
5
5
  module Decorator
6
6
  include Options
7
7
 
8
+ # @return [Definition]
8
9
  attr_reader :type
9
10
 
11
+ # @param [Definition] type
10
12
  def initialize(type, *)
11
13
  super
12
14
  @type = type
13
15
  end
14
16
 
17
+ # @return [Constructor]
15
18
  def constructor
16
19
  type.constructor
17
20
  end
18
21
 
22
+ # @param [Object] input
23
+ # @param [#call] block
24
+ # @return [Result]
19
25
  def try(input, &block)
20
26
  type.try(input, &block)
21
27
  end
22
28
 
29
+ # @param [Object] value
30
+ # @return [Boolean]
23
31
  def valid?(value)
24
32
  type.valid?(value)
25
33
  end
26
34
 
35
+ # @return [Boolean]
27
36
  def default?
28
37
  type.default?
29
38
  end
30
39
 
40
+ # @return [Boolean]
31
41
  def constrained?
32
42
  type.constrained?
33
43
  end
34
44
 
45
+ # @param [Symbol] meth
46
+ # @param [Boolean] include_private
47
+ # @return [Boolean]
35
48
  def respond_to_missing?(meth, include_private = false)
36
49
  super || type.respond_to?(meth)
37
50
  end
38
51
 
39
52
  private
40
53
 
54
+ # @param [Object] response
55
+ # @return [Boolean]
41
56
  def decorate?(response)
42
57
  response.kind_of?(type.class)
43
58
  end
44
59
 
60
+ # Delegates missing methods to {#type}
61
+ # @param [Symbol] meth
62
+ # @param [Array] args
63
+ # @param [#call] block
45
64
  def method_missing(meth, *args, &block)
46
65
  if type.respond_to?(meth)
47
66
  response = type.__send__(meth, *args, &block)
@@ -10,15 +10,20 @@ module Dry
10
10
  class Callable < Default
11
11
  include Dry::Equalizer(:type, :options)
12
12
 
13
+ # Evaluates given callable
14
+ # @return [Object]
13
15
  def evaluate
14
16
  value.call
15
17
  end
16
18
  end
17
19
 
20
+ # @return [Object]
18
21
  attr_reader :value
19
22
 
20
23
  alias_method :evaluate, :value
21
24
 
25
+ # @param [Object, #call] value
26
+ # @return [Default, Dry::Types::Default::Callable]
22
27
  def self.[](value)
23
28
  if value.respond_to?(:call)
24
29
  Callable
@@ -27,23 +32,32 @@ module Dry
27
32
  end
28
33
  end
29
34
 
35
+ # @param [Definition] type
36
+ # @param [Object] value
30
37
  def initialize(type, value, *)
31
38
  super
32
39
  @value = value
33
40
  end
34
41
 
42
+ # @param [Array] args see {Dry::Types::Builder#constrained}
43
+ # @return [Default]
35
44
  def constrained(*args)
36
45
  type.constrained(*args).default(value)
37
46
  end
38
47
 
48
+ # @return [true]
39
49
  def default?
40
50
  true
41
51
  end
42
52
 
53
+ # @param [Object] input
54
+ # @return [Success]
43
55
  def try(input)
44
56
  success(call(input))
45
57
  end
46
58
 
59
+ # @param [Object] input
60
+ # @return [Object] value passed through {#type} or {#default} value
47
61
  def call(input)
48
62
  if input.nil?
49
63
  evaluate
@@ -9,10 +9,14 @@ module Dry
9
9
  include Options
10
10
  include Builder
11
11
 
12
+ # @return [Hash]
12
13
  attr_reader :options
13
14
 
15
+ # @return [Class]
14
16
  attr_reader :primitive
15
17
 
18
+ # @param [Class] primitive
19
+ # @return [Definition]
16
20
  def self.[](primitive)
17
21
  if primitive == ::Array
18
22
  Types::Array
@@ -23,29 +27,41 @@ module Dry
23
27
  end
24
28
  end
25
29
 
30
+ # @param [Class] primitive
31
+ # @param [Hash] options
26
32
  def initialize(primitive, options = {})
27
33
  super
28
34
  @primitive = primitive
29
35
  freeze
30
36
  end
31
37
 
38
+ # @return [String]
32
39
  def name
33
40
  primitive.name
34
41
  end
35
42
 
43
+ # @return [false]
36
44
  def default?
37
45
  false
38
46
  end
39
47
 
48
+ # @return [false]
40
49
  def constrained?
41
50
  false
42
51
  end
43
52
 
53
+ # @param [Object] input
54
+ # @return [Object]
44
55
  def call(input)
45
56
  input
46
57
  end
47
58
  alias_method :[], :call
48
59
 
60
+ # @param [Object] input
61
+ # @param [#call] block
62
+ # @yieldparam [Failure] failure
63
+ # @yieldreturn [Result]
64
+ # @return [Result]
49
65
  def try(input, &block)
50
66
  if valid?(input)
51
67
  success(input)
@@ -55,18 +71,29 @@ module Dry
55
71
  end
56
72
  end
57
73
 
58
- def success(*args)
59
- Result::Success.new(*args)
74
+ # @param (see Dry::Types::Success#initialize)
75
+ # @return [Success]
76
+ def success(input)
77
+ Result::Success.new(input)
60
78
  end
61
79
 
62
- def failure(*args)
63
- Result::Failure.new(*args)
80
+
81
+ # @param (see Failure#initialize)
82
+ # @return [Failure]
83
+ def failure(input, error)
84
+ Result::Failure.new(input, error)
64
85
  end
65
86
 
87
+ # @param [Object] klass class of the result instance
88
+ # @param [Array] args arguments for the +klass#initialize+ method
89
+ # @return [Object] new instance of the given +klass+
66
90
  def result(klass, *args)
67
91
  klass.new(*args)
68
92
  end
69
93
 
94
+ # Checks whether value is of a #primitive class
95
+ # @param [Object] value
96
+ # @return [Boolean]
70
97
  def primitive?(value)
71
98
  value.is_a?(primitive)
72
99
  end
@@ -6,8 +6,15 @@ module Dry
6
6
  include Dry::Equalizer(:type, :options, :values)
7
7
  include Decorator
8
8
 
9
- attr_reader :values, :mapping
9
+ # @return [Array]
10
+ attr_reader :values
10
11
 
12
+ # @return [Hash]
13
+ attr_reader :mapping
14
+
15
+ # @param [Definition] type
16
+ # @param [Hash] options
17
+ # @option options [Array] :values
11
18
  def initialize(type, options)
12
19
  super
13
20
  @values = options.fetch(:values).freeze
@@ -15,6 +22,8 @@ module Dry
15
22
  @mapping = values.each_with_object({}) { |v, h| h[values.index(v)] = v }.freeze
16
23
  end
17
24
 
25
+ # @param [Object] input
26
+ # @return [Object]
18
27
  def call(input)
19
28
  value =
20
29
  if values.include?(input)
@@ -2,9 +2,13 @@ module Dry
2
2
  module Types
3
3
  extend Dry::Configurable
4
4
 
5
+ # @!attribute [r] namespace
6
+ # @return [Container{String => Definition}]
5
7
  setting :namespace, self
6
8
 
7
9
  class SchemaError < TypeError
10
+ # @param [String] key
11
+ # @param [Object] value
8
12
  def initialize(key, value)
9
13
  super("#{value.inspect} (#{value.class}) has invalid type for :#{key}")
10
14
  end
@@ -14,20 +18,27 @@ module Dry
14
18
  private_constant(:SchemaKeyError)
15
19
 
16
20
  class MissingKeyError < SchemaKeyError
21
+ # @param [String] key
17
22
  def initialize(key)
18
23
  super(":#{key} is missing in Hash input")
19
24
  end
20
25
  end
21
26
 
22
27
  class UnknownKeysError < SchemaKeyError
28
+ # @param [<String, Symbol>] keys
23
29
  def initialize(*keys)
24
30
  super("unexpected keys #{keys.inspect} in Hash input")
25
31
  end
26
32
  end
27
33
 
28
- ConstraintError = Class.new(TypeError) do
29
- attr_reader :result, :input
34
+ class ConstraintError < TypeError
35
+ # @return [String, #to_s]
36
+ attr_reader :result
37
+ # @return [Object]
38
+ attr_reader :input
30
39
 
40
+ # @param [String, #to_s] result
41
+ # @param [Object] input
31
42
  def initialize(result, input)
32
43
  @result = result
33
44
  @input = input
@@ -39,6 +50,7 @@ module Dry
39
50
  end
40
51
  end
41
52
 
53
+ # @return [String]
42
54
  def to_s
43
55
  "#{input.inspect} violates constraints (#{result} failed)"
44
56
  end
@@ -9,19 +9,27 @@ module Dry
9
9
  include Builder
10
10
  include Dry::Monads::Maybe::Mixin
11
11
 
12
+ # @param [Dry::Monads::Maybe, Object] input
13
+ # @return [Dry::Monads::Maybe]
12
14
  def call(input)
13
15
  input.is_a?(Dry::Monads::Maybe) ? input : Maybe(type[input])
14
16
  end
15
17
  alias_method :[], :call
16
18
 
19
+ # @param [Object] input
20
+ # @return [Result::Success]
17
21
  def try(input)
18
22
  Result::Success.new(Maybe(type[input]))
19
23
  end
20
24
 
25
+ # @return [true]
21
26
  def maybe?
22
27
  true
23
28
  end
24
29
 
30
+ # @param [Object] value
31
+ # @see Dry::Types::Builder#default
32
+ # @raise [ArgumentError] if nil provided as default value
25
33
  def default(value)
26
34
  if value.nil?
27
35
  raise ArgumentError, "nil cannot be used as a default of a maybe type"
@@ -32,6 +40,7 @@ module Dry
32
40
  end
33
41
 
34
42
  module Builder
43
+ # @return [Maybe]
35
44
  def maybe
36
45
  Maybe.new(Types['strict.nil'] | self)
37
46
  end
@@ -39,6 +48,9 @@ module Dry
39
48
 
40
49
  class Hash
41
50
  module MaybeTypes
51
+ # @param [Hash] result
52
+ # @param [Symbol] key
53
+ # @param [Definition] type
42
54
  def resolve_missing_value(result, key, type)
43
55
  if type.respond_to?(:maybe?) && type.maybe?
44
56
  result[key] = type[nil]
@@ -48,8 +60,13 @@ module Dry
48
60
  end
49
61
  end
50
62
 
51
- StrictWithDefaults.include MaybeTypes
52
- Schema.include MaybeTypes
63
+ class StrictWithDefaults < Strict
64
+ include MaybeTypes
65
+ end
66
+
67
+ class Schema < Hash
68
+ include MaybeTypes
69
+ end
53
70
  end
54
71
 
55
72
  # Register non-coercible maybe types