dry-types 0.14.1 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +631 -134
  3. data/LICENSE +17 -17
  4. data/README.md +15 -13
  5. data/dry-types.gemspec +27 -30
  6. data/lib/dry/types/any.rb +32 -12
  7. data/lib/dry/types/array/constructor.rb +32 -0
  8. data/lib/dry/types/array/member.rb +75 -16
  9. data/lib/dry/types/array.rb +19 -6
  10. data/lib/dry/types/builder.rb +131 -15
  11. data/lib/dry/types/builder_methods.rb +49 -20
  12. data/lib/dry/types/coercions/json.rb +43 -7
  13. data/lib/dry/types/coercions/params.rb +118 -31
  14. data/lib/dry/types/coercions.rb +76 -22
  15. data/lib/dry/types/compat.rb +0 -2
  16. data/lib/dry/types/compiler.rb +56 -41
  17. data/lib/dry/types/constrained/coercible.rb +36 -6
  18. data/lib/dry/types/constrained.rb +81 -32
  19. data/lib/dry/types/constraints.rb +18 -4
  20. data/lib/dry/types/constructor/function.rb +216 -0
  21. data/lib/dry/types/constructor/wrapper.rb +94 -0
  22. data/lib/dry/types/constructor.rb +126 -56
  23. data/lib/dry/types/container.rb +7 -0
  24. data/lib/dry/types/core.rb +54 -21
  25. data/lib/dry/types/decorator.rb +38 -17
  26. data/lib/dry/types/default.rb +61 -16
  27. data/lib/dry/types/enum.rb +43 -20
  28. data/lib/dry/types/errors.rb +75 -9
  29. data/lib/dry/types/extensions/maybe.rb +74 -16
  30. data/lib/dry/types/extensions/monads.rb +29 -0
  31. data/lib/dry/types/extensions.rb +7 -1
  32. data/lib/dry/types/fn_container.rb +6 -1
  33. data/lib/dry/types/hash/constructor.rb +33 -0
  34. data/lib/dry/types/hash.rb +86 -67
  35. data/lib/dry/types/inflector.rb +3 -1
  36. data/lib/dry/types/json.rb +18 -16
  37. data/lib/dry/types/lax.rb +75 -0
  38. data/lib/dry/types/map.rb +76 -33
  39. data/lib/dry/types/meta.rb +51 -0
  40. data/lib/dry/types/module.rb +120 -0
  41. data/lib/dry/types/nominal.rb +210 -0
  42. data/lib/dry/types/options.rb +13 -26
  43. data/lib/dry/types/params.rb +39 -25
  44. data/lib/dry/types/predicate_inferrer.rb +238 -0
  45. data/lib/dry/types/predicate_registry.rb +34 -0
  46. data/lib/dry/types/primitive_inferrer.rb +97 -0
  47. data/lib/dry/types/printable.rb +16 -0
  48. data/lib/dry/types/printer.rb +315 -0
  49. data/lib/dry/types/result.rb +29 -3
  50. data/lib/dry/types/schema/key.rb +156 -0
  51. data/lib/dry/types/schema.rb +408 -0
  52. data/lib/dry/types/spec/types.rb +103 -33
  53. data/lib/dry/types/sum.rb +84 -35
  54. data/lib/dry/types/type.rb +49 -0
  55. data/lib/dry/types/version.rb +3 -1
  56. data/lib/dry/types.rb +156 -76
  57. data/lib/dry-types.rb +3 -1
  58. metadata +65 -78
  59. data/.gitignore +0 -10
  60. data/.rspec +0 -2
  61. data/.travis.yml +0 -27
  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
  73. data/log/.gitkeep +0 -0
@@ -1,9 +1,18 @@
1
- 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"
2
7
 
3
8
  module Dry
4
9
  module Types
5
- class Constructor < Definition
6
- 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)
7
16
 
8
17
  # @return [#call]
9
18
  attr_reader :fn
@@ -11,118 +20,179 @@ module Dry
11
20
  # @return [Type]
12
21
  attr_reader :type
13
22
 
14
- undef :constrained?
23
+ undef :constrained?, :meta, :optional?, :primitive, :default?, :name
15
24
 
16
25
  # @param [Builder, Object] input
17
26
  # @param [Hash] options
18
27
  # @param [#call, nil] block
28
+ #
29
+ # @api public
19
30
  def self.new(input, **options, &block)
20
- type = input.is_a?(Builder) ? input : Definition.new(input)
21
- super(type, **options, &block)
31
+ type = input.is_a?(Builder) ? input : Nominal.new(input)
32
+ super(type, **options, fn: Function[options.fetch(:fn, block)])
22
33
  end
23
34
 
24
- # @param [Type] type
35
+ # @param [Builder, Object] input
25
36
  # @param [Hash] options
26
37
  # @param [#call, nil] block
27
- def initialize(type, **options, &block)
28
- @type = type
29
- @fn = options.fetch(:fn, block)
30
-
31
- raise ArgumentError, 'Missing constructor block' if fn.nil?
38
+ #
39
+ # @api public
40
+ def self.[](type, fn:, **options)
41
+ function = Function[fn]
32
42
 
33
- 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
34
48
  end
35
49
 
36
- # @return [Class]
37
- def primitive
38
- 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
39
59
  end
40
60
 
41
- # @return [String]
42
- def name
43
- 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)
44
73
  end
45
74
 
46
- def default?
47
- 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) }
48
81
  end
49
82
 
50
- # @param [Object] input
51
83
  # @return [Object]
52
- def call(input)
53
- type[fn[input]]
84
+ #
85
+ # @api private
86
+ def call_unsafe(input)
87
+ type.call_unsafe(fn.(input))
54
88
  end
55
- alias_method :[], :call
56
89
 
57
90
  # @param [Object] input
58
91
  # @param [#call,nil] block
92
+ #
59
93
  # @return [Logic::Result, Types::Result]
60
94
  # @return [Object] if block given and try fails
95
+ #
96
+ # @api public
61
97
  def try(input, &block)
62
- type.try(fn[input], &block)
63
- rescue TypeError, ArgumentError => e
64
- 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)
65
104
  end
66
105
 
106
+ # Build a new constructor by appending a block to the coercion function
107
+ #
67
108
  # @param [#call, nil] new_fn
68
109
  # @param [Hash] options
69
110
  # @param [#call, nil] block
111
+ #
70
112
  # @return [Constructor]
113
+ #
114
+ # @api public
71
115
  def constructor(new_fn = nil, **options, &block)
72
- left = new_fn || block
73
- right = fn
74
-
75
- with(options.merge(fn: -> input { left[right[input]] }))
76
- end
116
+ next_fn = Function[new_fn || block]
77
117
 
78
- # @param [Object] value
79
- # @return [Boolean]
80
- def valid?(value)
81
- constructed_value = fn[value]
82
- rescue NoMethodError, TypeError, ArgumentError
83
- false
84
- else
85
- type.valid?(constructed_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
86
123
  end
87
- alias_method :===, :valid?
124
+ alias_method :append, :constructor
125
+ alias_method :>>, :constructor
88
126
 
89
127
  # @return [Class]
128
+ #
129
+ # @api private
90
130
  def constrained_type
91
131
  Constrained::Coercible
92
132
  end
93
133
 
94
- # @api public
134
+ # @see Nominal#to_ast
95
135
  #
96
- # @see Definition#to_ast
136
+ # @api public
97
137
  def to_ast(meta: true)
98
- [:constructor, [type.to_ast(meta: meta),
99
- register_fn(fn),
100
- meta ? self.meta : EMPTY_HASH]]
138
+ [:constructor, [type.to_ast(meta: meta), fn.to_ast]]
101
139
  end
102
140
 
103
- 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
104
162
 
105
- def register_fn(fn)
106
- 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) }
107
170
  end
108
171
 
172
+ private
173
+
109
174
  # @param [Symbol] meth
110
175
  # @param [Boolean] include_private
111
176
  # @return [Boolean]
177
+ #
178
+ # @api private
112
179
  def respond_to_missing?(meth, include_private = false)
113
180
  super || type.respond_to?(meth)
114
181
  end
115
182
 
116
183
  # Delegates missing methods to {#type}
117
- # @param [Symbol] meth
184
+ #
185
+ # @param [Symbol] method
118
186
  # @param [Array] args
119
187
  # @param [#call, nil] block
120
- def method_missing(meth, *args, &block)
121
- if type.respond_to?(meth)
122
- 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)
123
193
 
124
- if response.kind_of?(Builder)
125
- self.class.new(response, options)
194
+ if response.is_a?(Type) && type.class.equal?(response.class)
195
+ response.constructor_type[response, **options]
126
196
  else
127
197
  response
128
198
  end
@@ -1,5 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/container"
4
+
1
5
  module Dry
2
6
  module Types
7
+ # Internal container for the built-in types
8
+ #
9
+ # @api private
3
10
  class Container
4
11
  include Dry::Container::Mixin
5
12
  end
@@ -1,8 +1,11 @@
1
- require 'dry/types/any'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/any"
2
4
 
3
5
  module Dry
4
6
  module Types
5
- COERCIBLE = {
7
+ # Primitives with {Kernel} coercion methods
8
+ KERNEL_COERCIBLE = {
6
9
  string: String,
7
10
  integer: Integer,
8
11
  float: Float,
@@ -11,9 +14,19 @@ module Dry
11
14
  hash: ::Hash
12
15
  }.freeze
13
16
 
17
+ # Primitives with coercions through by convention `to_*` methods
18
+ METHOD_COERCIBLE = {
19
+ symbol: Symbol
20
+ }.freeze
21
+
22
+ # By convention methods to coerce {METHOD_COERCIBLE} primitives
23
+ METHOD_COERCIBLE_METHODS = {
24
+ symbol: :to_sym
25
+ }.freeze
26
+
27
+ # Primitives that are non-coercible
14
28
  NON_COERCIBLE = {
15
29
  nil: NilClass,
16
- symbol: Symbol,
17
30
  class: Class,
18
31
  true: TrueClass,
19
32
  false: FalseClass,
@@ -23,44 +36,64 @@ module Dry
23
36
  range: Range
24
37
  }.freeze
25
38
 
26
- ALL_PRIMITIVES = COERCIBLE.merge(NON_COERCIBLE).freeze
39
+ # All built-in primitives
40
+ ALL_PRIMITIVES = [KERNEL_COERCIBLE, METHOD_COERCIBLE, NON_COERCIBLE].reduce(&:merge).freeze
41
+
42
+ # All coercible types
43
+ COERCIBLE = KERNEL_COERCIBLE.merge(METHOD_COERCIBLE).freeze
27
44
 
45
+ # All built-in primitives except {NilClass}
28
46
  NON_NIL = ALL_PRIMITIVES.reject { |name, _| name == :nil }.freeze
29
47
 
30
- # Register built-in types that are non-coercible through kernel methods
48
+ # Register generic types for {ALL_PRIMITIVES}
31
49
  ALL_PRIMITIVES.each do |name, primitive|
32
- register(name.to_s, Definition[primitive].new(primitive))
50
+ type = Nominal[primitive].new(primitive)
51
+ register("nominal.#{name}", type)
33
52
  end
34
53
 
35
- # Register strict built-in types that are non-coercible through kernel methods
54
+ # Register strict types for {ALL_PRIMITIVES}
36
55
  ALL_PRIMITIVES.each do |name, primitive|
37
- register("strict.#{name}", self[name.to_s].constrained(type: primitive))
56
+ type = self["nominal.#{name}"].constrained(type: primitive)
57
+ register(name.to_s, type)
58
+ register("strict.#{name}", type)
59
+ end
60
+
61
+ # Register {KERNEL_COERCIBLE} types
62
+ KERNEL_COERCIBLE.each do |name, primitive|
63
+ register("coercible.#{name}", self["nominal.#{name}"].constructor(Kernel.method(primitive.name)))
38
64
  end
39
65
 
40
- # Register built-in primitive types with kernel coercion methods
41
- COERCIBLE.each do |name, primitive|
42
- register("coercible.#{name}", self[name.to_s].constructor(Kernel.method(primitive.name)))
66
+ # Register {METHOD_COERCIBLE} types
67
+ METHOD_COERCIBLE.each_key do |name|
68
+ register(
69
+ "coercible.#{name}", self["nominal.#{name}"].constructor(&METHOD_COERCIBLE_METHODS[name])
70
+ )
43
71
  end
44
72
 
45
- # Register non-coercible optional types
73
+ # Register optional strict {NON_NIL} types
46
74
  NON_NIL.each_key do |name|
47
- register("optional.strict.#{name}", self["strict.#{name}"].optional)
75
+ type = self[name.to_s].optional
76
+ register("optional.strict.#{name}", type)
77
+ register("optional.#{name}", type)
48
78
  end
49
79
 
50
- # Register coercible optional types
80
+ # Register optional {COERCIBLE} types
51
81
  COERCIBLE.each_key do |name|
52
82
  register("optional.coercible.#{name}", self["coercible.#{name}"].optional)
53
83
  end
54
84
 
55
- # Register :bool since it's common and not a built-in Ruby type :(
56
- register("bool", self["true"] | self["false"])
57
- register("strict.bool", self["strict.true"] | self["strict.false"])
85
+ # Register `:bool` since it's common and not a built-in Ruby type :(
86
+ register("nominal.bool", self["nominal.true"] | self["nominal.false"])
87
+ bool = self["strict.true"] | self["strict.false"]
88
+ register("strict.bool", bool)
89
+ register("bool", bool)
58
90
 
59
91
  register("any", Any)
60
- register("object", self['any'])
92
+ register("nominal.any", Any)
93
+ register("strict.any", Any)
61
94
  end
62
95
  end
63
96
 
64
- require 'dry/types/coercions'
65
- require 'dry/types/params'
66
- require 'dry/types/json'
97
+ require "dry/types/coercions"
98
+ require "dry/types/params"
99
+ require "dry/types/json"
@@ -1,7 +1,12 @@
1
- require 'dry/types/options'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/options"
2
4
 
3
5
  module Dry
4
6
  module Types
7
+ # Common API for types
8
+ #
9
+ # @api public
5
10
  module Decorator
6
11
  include Options
7
12
 
@@ -9,63 +14,76 @@ module Dry
9
14
  attr_reader :type
10
15
 
11
16
  # @param [Type] type
12
- def initialize(type, *)
17
+ def initialize(type, *, **)
13
18
  super
14
19
  @type = type
15
20
  end
16
21
 
17
22
  # @param [Object] input
18
23
  # @param [#call, nil] block
24
+ #
19
25
  # @return [Result,Logic::Result]
20
26
  # @return [Object] if block given and try fails
27
+ #
28
+ # @api public
21
29
  def try(input, &block)
22
30
  type.try(input, &block)
23
31
  end
24
32
 
25
- # @param [Object] value
26
- # @return [Boolean]
27
- def valid?(value)
28
- type.valid?(value)
29
- end
30
- alias_method :===, :valid?
31
-
32
33
  # @return [Boolean]
34
+ #
35
+ # @api public
33
36
  def default?
34
37
  type.default?
35
38
  end
36
39
 
37
40
  # @return [Boolean]
41
+ #
42
+ # @api public
38
43
  def constrained?
39
44
  type.constrained?
40
45
  end
41
46
 
42
- # @return [Sum]
43
- def optional
44
- Types['strict.nil'] | self
45
- end
46
-
47
47
  # @param [Symbol] meth
48
48
  # @param [Boolean] include_private
49
+ #
49
50
  # @return [Boolean]
51
+ #
52
+ # @api public
50
53
  def respond_to_missing?(meth, include_private = false)
51
54
  super || type.respond_to?(meth)
52
55
  end
53
56
 
57
+ # Wrap the type with a proc
58
+ #
59
+ # @return [Proc]
60
+ #
61
+ # @api public
62
+ def to_proc
63
+ proc { |value| self.(value) }
64
+ end
65
+
54
66
  private
55
67
 
56
68
  # @param [Object] response
69
+ #
57
70
  # @return [Boolean]
71
+ #
72
+ # @api private
58
73
  def decorate?(response)
59
- response.kind_of?(type.class)
74
+ response.is_a?(type.class)
60
75
  end
61
76
 
62
77
  # Delegates missing methods to {#type}
78
+ #
63
79
  # @param [Symbol] meth
64
80
  # @param [Array] args
65
81
  # @param [#call, nil] block
82
+ #
83
+ # @api private
66
84
  def method_missing(meth, *args, &block)
67
85
  if type.respond_to?(meth)
68
- response = type.__send__(meth, *args, &block)
86
+ response = type.public_send(meth, *args, &block)
69
87
 
70
88
  if decorate?(response)
71
89
  __new__(response)
@@ -76,10 +94,13 @@ module Dry
76
94
  super
77
95
  end
78
96
  end
97
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
79
98
 
80
99
  # Replace underlying type
100
+ #
101
+ # @api private
81
102
  def __new__(type)
82
- self.class.new(type, options)
103
+ self.class.new(type, *@__args__.drop(1), **@options)
83
104
  end
84
105
  end
85
106
  end
@@ -1,30 +1,46 @@
1
- require 'dry/types/decorator'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/equalizer"
4
+ require "dry/types/decorator"
2
5
 
3
6
  module Dry
4
7
  module Types
8
+ # Default types are useful when a missing value should be replaced by a default one
9
+ #
10
+ # @api public
5
11
  class Default
6
- include Type
7
- include Dry::Equalizer(:type, :options, :value)
8
- include Decorator
9
- include Builder
10
-
12
+ # @api private
11
13
  class Callable < Default
12
- include Dry::Equalizer(:type, :options)
14
+ include Dry::Equalizer(:type, inspect: false, immutable: true)
13
15
 
14
16
  # Evaluates given callable
15
17
  # @return [Object]
16
18
  def evaluate
17
19
  value.call(type)
18
20
  end
21
+
22
+ # @return [true]
23
+ def callable?
24
+ true
25
+ end
19
26
  end
20
27
 
28
+ include Type
29
+ include Decorator
30
+ include Builder
31
+ include Printable
32
+ include Dry::Equalizer(:type, :value, inspect: false, immutable: true)
33
+
21
34
  # @return [Object]
22
35
  attr_reader :value
23
36
 
24
37
  alias_method :evaluate, :value
25
38
 
26
39
  # @param [Object, #call] value
40
+ #
27
41
  # @return [Class] {Default} or {Default::Callable}
42
+ #
43
+ # @api private
28
44
  def self.[](value)
29
45
  if value.respond_to?(:call)
30
46
  Callable
@@ -35,49 +51,78 @@ module Dry
35
51
 
36
52
  # @param [Type] type
37
53
  # @param [Object] value
54
+ #
55
+ # @api private
38
56
  def initialize(type, value, **options)
39
57
  super
40
58
  @value = value
41
59
  end
42
60
 
61
+ # Build a constrained type
62
+ #
43
63
  # @param [Array] args see {Dry::Types::Builder#constrained}
64
+ #
44
65
  # @return [Default]
66
+ #
67
+ # @api public
45
68
  def constrained(*args)
46
69
  type.constrained(*args).default(value)
47
70
  end
48
71
 
49
72
  # @return [true]
73
+ #
74
+ # @api public
50
75
  def default?
51
76
  true
52
77
  end
53
78
 
54
79
  # @param [Object] input
80
+ #
55
81
  # @return [Result::Success]
82
+ #
83
+ # @api public
56
84
  def try(input)
57
85
  success(call(input))
58
86
  end
59
87
 
88
+ # @return [Boolean]
89
+ #
90
+ # @api public
60
91
  def valid?(value = Undefined)
61
- value.equal?(Undefined) || super
92
+ Undefined.equal?(value) || super
62
93
  end
63
94
 
64
95
  # @param [Object] input
96
+ #
65
97
  # @return [Object] value passed through {#type} or {#default} value
66
- def call(input = Undefined)
98
+ #
99
+ # @api private
100
+ def call_unsafe(input = Undefined)
67
101
  if input.equal?(Undefined)
68
102
  evaluate
69
103
  else
70
- output = type[input]
71
- output.nil? ? evaluate : output
104
+ Undefined.default(type.call_unsafe(input)) { evaluate }
72
105
  end
73
106
  end
74
- alias_method :[], :call
75
107
 
76
- private
108
+ # @param [Object] input
109
+ #
110
+ # @return [Object] value passed through {#type} or {#default} value
111
+ #
112
+ # @api private
113
+ def call_safe(input = Undefined, &block)
114
+ if input.equal?(Undefined)
115
+ evaluate
116
+ else
117
+ Undefined.default(type.call_safe(input, &block)) { evaluate }
118
+ end
119
+ end
77
120
 
78
- # Replace underlying type
79
- def __new__(type)
80
- self.class.new(type, value, options)
121
+ # @return [false]
122
+ #
123
+ # @api private
124
+ def callable?
125
+ false
81
126
  end
82
127
  end
83
128
  end