dry-types 0.13.2 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +763 -233
  3. data/LICENSE +17 -17
  4. data/README.md +15 -13
  5. data/dry-types.gemspec +28 -28
  6. data/lib/dry-types.rb +3 -1
  7. data/lib/dry/types.rb +156 -76
  8. data/lib/dry/types/any.rb +32 -12
  9. data/lib/dry/types/array.rb +19 -6
  10. data/lib/dry/types/array/constructor.rb +32 -0
  11. data/lib/dry/types/array/member.rb +75 -16
  12. data/lib/dry/types/builder.rb +131 -15
  13. data/lib/dry/types/builder_methods.rb +49 -20
  14. data/lib/dry/types/coercions.rb +76 -22
  15. data/lib/dry/types/coercions/json.rb +43 -7
  16. data/lib/dry/types/coercions/params.rb +118 -31
  17. data/lib/dry/types/compat.rb +0 -2
  18. data/lib/dry/types/compiler.rb +56 -41
  19. data/lib/dry/types/constrained.rb +81 -32
  20. data/lib/dry/types/constrained/coercible.rb +36 -6
  21. data/lib/dry/types/constraints.rb +18 -4
  22. data/lib/dry/types/constructor.rb +127 -54
  23. data/lib/dry/types/constructor/function.rb +216 -0
  24. data/lib/dry/types/constructor/wrapper.rb +94 -0
  25. data/lib/dry/types/container.rb +7 -0
  26. data/lib/dry/types/core.rb +54 -21
  27. data/lib/dry/types/decorator.rb +38 -17
  28. data/lib/dry/types/default.rb +61 -16
  29. data/lib/dry/types/enum.rb +43 -20
  30. data/lib/dry/types/errors.rb +75 -9
  31. data/lib/dry/types/extensions.rb +7 -1
  32. data/lib/dry/types/extensions/maybe.rb +74 -16
  33. data/lib/dry/types/extensions/monads.rb +29 -0
  34. data/lib/dry/types/fn_container.rb +6 -1
  35. data/lib/dry/types/hash.rb +86 -67
  36. data/lib/dry/types/hash/constructor.rb +33 -0
  37. data/lib/dry/types/inflector.rb +3 -1
  38. data/lib/dry/types/json.rb +18 -16
  39. data/lib/dry/types/lax.rb +75 -0
  40. data/lib/dry/types/map.rb +76 -33
  41. data/lib/dry/types/meta.rb +51 -0
  42. data/lib/dry/types/module.rb +120 -0
  43. data/lib/dry/types/nominal.rb +210 -0
  44. data/lib/dry/types/options.rb +13 -26
  45. data/lib/dry/types/params.rb +39 -25
  46. data/lib/dry/types/predicate_inferrer.rb +238 -0
  47. data/lib/dry/types/predicate_registry.rb +34 -0
  48. data/lib/dry/types/primitive_inferrer.rb +97 -0
  49. data/lib/dry/types/printable.rb +16 -0
  50. data/lib/dry/types/printer.rb +315 -0
  51. data/lib/dry/types/result.rb +29 -3
  52. data/lib/dry/types/schema.rb +408 -0
  53. data/lib/dry/types/schema/key.rb +156 -0
  54. data/lib/dry/types/spec/types.rb +103 -33
  55. data/lib/dry/types/sum.rb +84 -35
  56. data/lib/dry/types/type.rb +49 -0
  57. data/lib/dry/types/version.rb +3 -1
  58. metadata +68 -79
  59. data/.gitignore +0 -10
  60. data/.rspec +0 -2
  61. data/.travis.yml +0 -29
  62. data/.yardopts +0 -5
  63. data/CONTRIBUTING.md +0 -29
  64. data/Gemfile +0 -24
  65. data/Rakefile +0 -20
  66. data/benchmarks/hash_schemas.rb +0 -51
  67. data/lib/dry/types/compat/form_types.rb +0 -27
  68. data/lib/dry/types/compat/int.rb +0 -14
  69. data/lib/dry/types/definition.rb +0 -113
  70. data/lib/dry/types/hash/schema.rb +0 -199
  71. data/lib/dry/types/hash/schema_builder.rb +0 -75
  72. data/lib/dry/types/safe.rb +0 -59
@@ -1,2 +0,0 @@
1
- require 'dry/types/compat/int'
2
- require 'dry/types/compat/form_types'
@@ -1,6 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/deprecations"
4
+
1
5
  module Dry
2
6
  module Types
7
+ # @api private
3
8
  class Compiler
9
+ extend ::Dry::Core::Deprecations[:'dry-types']
10
+
4
11
  attr_reader :registry
5
12
 
6
13
  def initialize(registry)
@@ -13,33 +20,34 @@ module Dry
13
20
 
14
21
  def visit(node)
15
22
  type, body = node
16
- send(:"visit_#{ type }", body)
23
+ send(:"visit_#{type}", body)
17
24
  end
18
25
 
19
26
  def visit_constrained(node)
20
- definition, rule, meta = node
21
- Types::Constrained.new(visit(definition), rule: visit_rule(rule)).meta(meta)
27
+ nominal, rule = node
28
+ type = visit(nominal)
29
+ type.constrained_type.new(type, rule: visit_rule(rule))
22
30
  end
23
31
 
24
32
  def visit_constructor(node)
25
- definition, fn_register_name, meta = node
26
- fn = Dry::Types::FnContainer[fn_register_name]
27
- primitive = visit(definition)
28
- Types::Constructor.new(primitive, meta: meta, fn: fn)
33
+ nominal, fn = node
34
+ primitive = visit(nominal)
35
+ primitive.constructor(compile_fn(fn))
29
36
  end
30
37
 
31
- def visit_safe(node)
32
- ast, meta = node
33
- Types::Safe.new(visit(ast), meta: meta)
38
+ def visit_lax(node)
39
+ Types::Lax.new(visit(node))
34
40
  end
41
+ deprecate(:visit_safe, :visit_lax)
35
42
 
36
- def visit_definition(node)
43
+ def visit_nominal(node)
37
44
  type, meta = node
45
+ nominal_name = "nominal.#{Types.identifier(type)}"
38
46
 
39
- if registry.registered?(type)
40
- registry[type].meta(meta)
47
+ if registry.registered?(nominal_name)
48
+ registry[nominal_name].meta(meta)
41
49
  else
42
- Definition.new(type, meta: meta)
50
+ Nominal.new(type, meta: meta)
43
51
  end
44
52
  end
45
53
 
@@ -55,65 +63,72 @@ module Dry
55
63
  def visit_array(node)
56
64
  member, meta = node
57
65
  member = member.is_a?(Class) ? member : visit(member)
58
- registry['array'].of(member).meta(meta)
66
+ registry["nominal.array"].of(member).meta(meta)
59
67
  end
60
68
 
61
69
  def visit_hash(node)
62
- constructor, schema, meta = node
63
- merge_with('hash', constructor, schema).meta(meta)
70
+ opts, meta = node
71
+ registry["nominal.hash"].with(**opts, meta: meta)
64
72
  end
65
73
 
66
- def visit_hash_schema(node)
67
- schema, meta = node
68
- merge_with_schema('hash', schema).meta(meta)
74
+ def visit_schema(node)
75
+ keys, options, meta = node
76
+ registry["nominal.hash"].schema(keys.map { |key| visit(key) }).with(**options, meta: meta)
69
77
  end
70
78
 
71
79
  def visit_json_hash(node)
72
- schema, meta = node
73
- merge_with('json.hash', :symbolized, schema).meta(meta)
80
+ keys, meta = node
81
+ registry["json.hash"].schema(keys.map { |key| visit(key) }, meta)
74
82
  end
75
83
 
76
84
  def visit_json_array(node)
77
85
  member, meta = node
78
- registry['json.array'].of(visit(member)).meta(meta)
86
+ registry["json.array"].of(visit(member)).meta(meta)
79
87
  end
80
88
 
81
89
  def visit_params_hash(node)
82
- schema, meta = node
83
- merge_with('params.hash', :symbolized, schema).meta(meta)
90
+ keys, meta = node
91
+ registry["params.hash"].schema(keys.map { |key| visit(key) }, meta)
84
92
  end
85
93
 
86
94
  def visit_params_array(node)
87
95
  member, meta = node
88
- registry['params.array'].of(visit(member)).meta(meta)
96
+ registry["params.array"].of(visit(member)).meta(meta)
89
97
  end
90
98
 
91
- def visit_member(node)
92
- name, type = node
93
- { name => visit(type) }
99
+ def visit_key(node)
100
+ name, required, type = node
101
+ Schema::Key.new(visit(type), name, required: required)
94
102
  end
95
103
 
96
104
  def visit_enum(node)
97
- type, mapping, meta = node
98
- Enum.new(visit(type), mapping: mapping, meta: meta)
105
+ type, mapping = node
106
+ Enum.new(visit(type), mapping: mapping)
99
107
  end
100
108
 
101
109
  def visit_map(node)
102
110
  key_type, value_type, meta = node
103
- registry['hash'].map(visit(key_type), visit(value_type)).meta(meta)
111
+ registry["nominal.hash"].map(visit(key_type), visit(value_type)).meta(meta)
104
112
  end
105
113
 
106
- def merge_with(hash_id, constructor, schema)
107
- registry[hash_id].schema(
108
- schema.map { |key| visit(key) }.reduce({}, :update),
109
- constructor
110
- )
114
+ def visit_any(meta)
115
+ registry["any"].meta(meta)
111
116
  end
112
117
 
113
- def merge_with_schema(hash_id, schema)
114
- registry[hash_id].instantiate(
115
- schema.map { |key| visit(key) }.reduce({}, :update)
116
- )
118
+ def compile_fn(fn)
119
+ type, *node = fn
120
+
121
+ case type
122
+ when :id
123
+ Dry::Types::FnContainer[node.fetch(0)]
124
+ when :callable
125
+ node.fetch(0)
126
+ when :method
127
+ target, method = node
128
+ target.method(method)
129
+ else
130
+ raise ArgumentError, "Cannot build callable from #{fn.inspect}"
131
+ end
117
132
  end
118
133
  end
119
134
  end
@@ -1,93 +1,142 @@
1
- require 'dry/types/decorator'
2
- require 'dry/types/constraints'
3
- require 'dry/types/constrained/coercible'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/equalizer"
4
+ require "dry/types/decorator"
5
+ require "dry/types/constraints"
6
+ require "dry/types/constrained/coercible"
4
7
 
5
8
  module Dry
6
9
  module Types
10
+ # Constrained types apply rules to the input
11
+ #
12
+ # @api public
7
13
  class Constrained
8
14
  include Type
9
- include Dry::Equalizer(:type, :options, :rule, :meta)
10
15
  include Decorator
11
16
  include Builder
17
+ include Printable
18
+ include Dry::Equalizer(:type, :rule, inspect: false, immutable: true)
12
19
 
13
20
  # @return [Dry::Logic::Rule]
14
21
  attr_reader :rule
15
22
 
16
23
  # @param [Type] type
24
+ #
17
25
  # @param [Hash] options
18
- def initialize(type, options)
26
+ #
27
+ # @api public
28
+ def initialize(type, **options)
19
29
  super
20
30
  @rule = options.fetch(:rule)
21
31
  end
22
32
 
23
- # @param [Object] input
24
33
  # @return [Object]
25
- # @raise [ConstraintError]
26
- def call(input)
27
- try(input) do |result|
34
+ #
35
+ # @api private
36
+ def call_unsafe(input)
37
+ result = rule.(input)
38
+
39
+ if result.success?
40
+ type.call_unsafe(input)
41
+ else
28
42
  raise ConstraintError.new(result, input)
29
- end.input
43
+ end
44
+ end
45
+
46
+ # @return [Object]
47
+ #
48
+ # @api private
49
+ def call_safe(input, &block)
50
+ if rule[input]
51
+ type.call_safe(input, &block)
52
+ else
53
+ yield
54
+ end
30
55
  end
31
- alias_method :[], :call
32
-
33
- # @param [Object] input
34
- # @param [#call,nil] block
35
- # @yieldparam [Failure] failure
36
- # @yieldreturn [Result]
37
- # @return [Logic::Result, Result]
38
- # @return [Object] if block given and try fails
56
+
57
+ # Safe coercion attempt. It is similar to #call with a
58
+ # block given but returns a Result instance with metadata
59
+ # about errors (if any).
60
+ #
61
+ # @overload try(input)
62
+ # @param [Object] input
63
+ # @return [Logic::Result]
64
+ #
65
+ # @overload try(input)
66
+ # @param [Object] input
67
+ # @yieldparam [Failure] failure
68
+ # @yieldreturn [Object]
69
+ # @return [Object]
70
+ #
71
+ # @api public
39
72
  def try(input, &block)
40
73
  result = rule.(input)
41
74
 
42
75
  if result.success?
43
76
  type.try(input, &block)
44
77
  else
45
- failure = failure(input, result)
46
- block ? yield(failure) : failure
78
+ failure = failure(input, ConstraintError.new(result, input))
79
+ block_given? ? yield(failure) : failure
47
80
  end
48
81
  end
49
82
 
50
- # @param [Object] value
51
- # @return [Boolean]
52
- def valid?(value)
53
- rule.(value).success? && type.valid?(value)
54
- end
55
-
56
83
  # @param [Hash] options
57
84
  # The options hash provided to {Types.Rule} and combined
58
85
  # using {&} with previous {#rule}
86
+ #
59
87
  # @return [Constrained]
88
+ #
60
89
  # @see Dry::Logic::Operators#and
90
+ #
91
+ # @api public
61
92
  def constrained(options)
62
93
  with(rule: rule & Types.Rule(options))
63
94
  end
64
95
 
65
96
  # @return [true]
97
+ #
98
+ # @api public
66
99
  def constrained?
67
100
  true
68
101
  end
69
102
 
70
103
  # @param [Object] value
104
+ #
71
105
  # @return [Boolean]
106
+ #
107
+ # @api public
72
108
  def ===(value)
73
109
  valid?(value)
74
110
  end
75
111
 
76
- # @api public
112
+ # Build lax type. Constraints are not applicable to lax types hence unwrapping
77
113
  #
78
- # @see Definition#to_ast
114
+ # @return [Lax]
115
+ # @api public
116
+ def lax
117
+ type.lax
118
+ end
119
+
120
+ # @see Nominal#to_ast
121
+ # @api public
79
122
  def to_ast(meta: true)
80
- [:constrained, [type.to_ast(meta: meta),
81
- rule.to_ast,
82
- meta ? self.meta : EMPTY_HASH]]
123
+ [:constrained, [type.to_ast(meta: meta), rule.to_ast]]
124
+ end
125
+
126
+ # @api private
127
+ def constructor_type
128
+ type.constructor_type
83
129
  end
84
130
 
85
131
  private
86
132
 
87
133
  # @param [Object] response
134
+ #
88
135
  # @return [Boolean]
136
+ #
137
+ # @api private
89
138
  def decorate?(response)
90
- super || response.kind_of?(Constructor)
139
+ super || response.is_a?(Constructor)
91
140
  end
92
141
  end
93
142
  end
@@ -1,12 +1,42 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  module Types
3
5
  class Constrained
6
+ # Common coercion-related API for constrained types
7
+ #
8
+ # @api public
4
9
  class Coercible < Constrained
5
- # @param [Object] input
6
- # @param [#call,nil] block
7
- # @yieldparam [Failure] failure
8
- # @yieldreturn [Result]
9
- # @return [Result,nil]
10
+ # @return [Object]
11
+ #
12
+ # @api private
13
+ def call_unsafe(input)
14
+ coerced = type.call_unsafe(input)
15
+ result = rule.(coerced)
16
+
17
+ if result.success?
18
+ coerced
19
+ else
20
+ raise ConstraintError.new(result, input)
21
+ end
22
+ end
23
+
24
+ # @return [Object]
25
+ #
26
+ # @api private
27
+ def call_safe(input)
28
+ coerced = type.call_safe(input) { return yield }
29
+
30
+ if rule[coerced]
31
+ coerced
32
+ else
33
+ yield(coerced)
34
+ end
35
+ end
36
+
37
+ # @see Dry::Types::Constrained#try
38
+ #
39
+ # @api public
10
40
  def try(input, &block)
11
41
  result = type.try(input)
12
42
 
@@ -16,7 +46,7 @@ module Dry
16
46
  if validation.success?
17
47
  result
18
48
  else
19
- failure = failure(result.input, validation)
49
+ failure = failure(result.input, ConstraintError.new(validation, input))
20
50
  block ? yield(failure) : failure
21
51
  end
22
52
  else
@@ -1,18 +1,32 @@
1
- require 'dry/logic/rule_compiler'
2
- require 'dry/logic/predicates'
3
- require 'dry/logic/rule/predicate'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/logic/rule_compiler"
4
+ require "dry/logic/predicates"
5
+ require "dry/logic/rule/predicate"
4
6
 
5
7
  module Dry
8
+ # Helper methods for constraint types
9
+ #
10
+ # @api public
6
11
  module Types
7
12
  # @param [Hash] options
13
+ #
8
14
  # @return [Dry::Logic::Rule]
15
+ #
16
+ # @api public
9
17
  def self.Rule(options)
10
18
  rule_compiler.(
11
- options.map { |key, val| Logic::Rule::Predicate.new(Logic::Predicates[:"#{key}?"]).curry(val).to_ast }
19
+ options.map { |key, val|
20
+ Logic::Rule::Predicate.build(
21
+ Logic::Predicates[:"#{key}?"]
22
+ ).curry(val).to_ast
23
+ }
12
24
  ).reduce(:and)
13
25
  end
14
26
 
15
27
  # @return [Dry::Logic::RuleCompiler]
28
+ #
29
+ # @api private
16
30
  def self.rule_compiler
17
31
  @rule_compiler ||= Logic::RuleCompiler.new(Logic::Predicates)
18
32
  end
@@ -1,10 +1,18 @@
1
- require 'dry/types/decorator'
2
- require 'dry/types/fn_container'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/equalizer"
4
+ require "dry/types/fn_container"
5
+ require "dry/types/constructor/function"
6
+ require "dry/types/constructor/wrapper"
3
7
 
4
8
  module Dry
5
9
  module Types
6
- class Constructor < Definition
7
- include Dry::Equalizer(:type, :options, :meta)
10
+ # Constructor types apply a function to the input that is supposed to return
11
+ # a new value. Coercion is a common use case for constructor types.
12
+ #
13
+ # @api public
14
+ class Constructor < Nominal
15
+ include Dry::Equalizer(:type, :options, inspect: false, immutable: true)
8
16
 
9
17
  # @return [#call]
10
18
  attr_reader :fn
@@ -12,114 +20,179 @@ module Dry
12
20
  # @return [Type]
13
21
  attr_reader :type
14
22
 
15
- undef :constrained?
23
+ undef :constrained?, :meta, :optional?, :primitive, :default?, :name
16
24
 
17
25
  # @param [Builder, Object] input
18
26
  # @param [Hash] options
19
27
  # @param [#call, nil] block
20
- def self.new(input, options = {}, &block)
21
- type = input.is_a?(Builder) ? input : Definition.new(input)
22
- super(type, options, &block)
28
+ #
29
+ # @api public
30
+ def self.new(input, **options, &block)
31
+ type = input.is_a?(Builder) ? input : Nominal.new(input)
32
+ super(type, **options, fn: Function[options.fetch(:fn, block)])
23
33
  end
24
34
 
25
- # @param [Type] type
35
+ # @param [Builder, Object] input
26
36
  # @param [Hash] options
27
37
  # @param [#call, nil] block
28
- def initialize(type, options = {}, &block)
29
- @type = type
30
- @fn = options.fetch(:fn, block)
31
-
32
- raise ArgumentError, 'Missing constructor block' if fn.nil?
38
+ #
39
+ # @api public
40
+ def self.[](type, fn:, **options)
41
+ function = Function[fn]
33
42
 
34
- super(type, **options, fn: fn)
43
+ if function.wrapper?
44
+ wrapper_type.new(type, fn: function, **options)
45
+ else
46
+ new(type, fn: function, **options)
47
+ end
35
48
  end
36
49
 
37
- # @return [Class]
38
- def primitive
39
- type.primitive
50
+ # @api private
51
+ def self.wrapper_type
52
+ @wrapper_type ||= begin
53
+ if self < Wrapper
54
+ self
55
+ else
56
+ const_set(:Wrapping, ::Class.new(self).include(Wrapper))
57
+ end
58
+ end
40
59
  end
41
60
 
42
- # @return [String]
43
- def name
44
- type.name
61
+ # Instantiate a new constructor type instance
62
+ #
63
+ # @param [Type] type
64
+ # @param [Function] fn
65
+ # @param [Hash] options
66
+ #
67
+ # @api private
68
+ def initialize(type, fn: nil, **options)
69
+ @type = type
70
+ @fn = fn
71
+
72
+ super(type, **options, fn: fn)
45
73
  end
46
74
 
47
- def default?
48
- type.default?
75
+ # @return [Object]
76
+ #
77
+ # @api private
78
+ def call_safe(input)
79
+ coerced = fn.(input) { |output = input| return yield(output) }
80
+ type.call_safe(coerced) { |output = coerced| yield(output) }
49
81
  end
50
82
 
51
- # @param [Object] input
52
83
  # @return [Object]
53
- def call(input)
54
- type[fn[input]]
84
+ #
85
+ # @api private
86
+ def call_unsafe(input)
87
+ type.call_unsafe(fn.(input))
55
88
  end
56
- alias_method :[], :call
57
89
 
58
90
  # @param [Object] input
59
91
  # @param [#call,nil] block
92
+ #
60
93
  # @return [Logic::Result, Types::Result]
61
94
  # @return [Object] if block given and try fails
95
+ #
96
+ # @api public
62
97
  def try(input, &block)
63
- type.try(fn[input], &block)
64
- rescue TypeError, ArgumentError => e
65
- failure(input, e.message)
98
+ value = fn.(input)
99
+ rescue CoercionError => e
100
+ failure = failure(input, e)
101
+ block_given? ? yield(failure) : failure
102
+ else
103
+ type.try(value, &block)
66
104
  end
67
105
 
106
+ # Build a new constructor by appending a block to the coercion function
107
+ #
68
108
  # @param [#call, nil] new_fn
69
109
  # @param [Hash] options
70
110
  # @param [#call, nil] block
111
+ #
71
112
  # @return [Constructor]
113
+ #
114
+ # @api public
72
115
  def constructor(new_fn = nil, **options, &block)
73
- left = new_fn || block
74
- right = fn
75
-
76
- with(options.merge(fn: -> input { left[right[input]] }))
77
- end
116
+ next_fn = Function[new_fn || block]
78
117
 
79
- # @param [Object] value
80
- # @return [Boolean]
81
- def valid?(value)
82
- type.valid?(value)
118
+ if next_fn.wrapper?
119
+ self.class.wrapper_type.new(with(**options), fn: next_fn)
120
+ else
121
+ with(**options, fn: fn >> next_fn)
122
+ end
83
123
  end
84
- alias_method :===, :valid?
124
+ alias_method :append, :constructor
125
+ alias_method :>>, :constructor
85
126
 
86
127
  # @return [Class]
128
+ #
129
+ # @api private
87
130
  def constrained_type
88
131
  Constrained::Coercible
89
132
  end
90
133
 
91
- # @api public
134
+ # @see Nominal#to_ast
92
135
  #
93
- # @see Definition#to_ast
136
+ # @api public
94
137
  def to_ast(meta: true)
95
- [:constructor, [type.to_ast(meta: meta),
96
- register_fn(fn),
97
- meta ? self.meta : EMPTY_HASH]]
138
+ [:constructor, [type.to_ast(meta: meta), fn.to_ast]]
98
139
  end
99
140
 
100
- private
141
+ # Build a new constructor by prepending a block to the coercion function
142
+ #
143
+ # @param [#call, nil] new_fn
144
+ # @param [Hash] options
145
+ # @param [#call, nil] block
146
+ #
147
+ # @return [Constructor]
148
+ #
149
+ # @api public
150
+ def prepend(new_fn = nil, **options, &block)
151
+ with(**options, fn: fn << (new_fn || block))
152
+ end
153
+ alias_method :<<, :prepend
154
+
155
+ # Build a lax type
156
+ #
157
+ # @return [Lax]
158
+ # @api public
159
+ def lax
160
+ Lax.new(constructor_type[type.lax, **options])
161
+ end
101
162
 
102
- def register_fn(fn)
103
- Dry::Types::FnContainer.register(fn)
163
+ # Wrap the type with a proc
164
+ #
165
+ # @return [Proc]
166
+ #
167
+ # @api public
168
+ def to_proc
169
+ proc { |value| self.(value) }
104
170
  end
105
171
 
172
+ private
173
+
106
174
  # @param [Symbol] meth
107
175
  # @param [Boolean] include_private
108
176
  # @return [Boolean]
177
+ #
178
+ # @api private
109
179
  def respond_to_missing?(meth, include_private = false)
110
180
  super || type.respond_to?(meth)
111
181
  end
112
182
 
113
183
  # Delegates missing methods to {#type}
114
- # @param [Symbol] meth
184
+ #
185
+ # @param [Symbol] method
115
186
  # @param [Array] args
116
187
  # @param [#call, nil] block
117
- def method_missing(meth, *args, &block)
118
- if type.respond_to?(meth)
119
- response = type.__send__(meth, *args, &block)
188
+ #
189
+ # @api private
190
+ def method_missing(method, *args, &block)
191
+ if type.respond_to?(method)
192
+ response = type.public_send(method, *args, &block)
120
193
 
121
- if response.kind_of?(Builder)
122
- self.class.new(response, options)
194
+ if response.is_a?(Type) && type.class.equal?(response.class)
195
+ response.constructor_type[response, **options]
123
196
  else
124
197
  response
125
198
  end