class Dry::Types::Constructor
Constructor
types apply a function to the input that is supposed to return a new value. Coercion is a common use case for constructor types.
@api public
@api public
Attributes
@return [#call]
@return [Type]
Public Class Methods
@param [Builder, Object] input @param [Hash] options @param [#call, nil] block
@api public
# File lib/dry/types/constructor.rb, line 40 def self.[](type, fn:, **options) function = Function[fn] if function.wrapper? wrapper_type.new(type, fn: function, **options) else new(type, fn: function, **options) end end
@param [Builder, Object] input @param [Hash] options @param [#call, nil] block
@api public
# File lib/dry/types/constructor.rb, line 30 def self.new(input, **options, &block) type = input.is_a?(Builder) ? input : Nominal.new(input) super(type, **options, fn: Function[options.fetch(:fn, block)]) end
Instantiate a new constructor type instance
@param [Type] type @param [Function] fn @param [Hash] options
@api private
# File lib/dry/types/constructor.rb, line 68 def initialize(type, fn: nil, **options) @type = type @fn = fn super(type, **options, fn: fn) end
@api private
# File lib/dry/types/constructor.rb, line 51 def self.wrapper_type @wrapper_type ||= begin if self < Wrapper self else const_set(:Wrapping, ::Class.new(self).include(Wrapper)) end end end
Public Instance Methods
@return [Object]
@api private
# File lib/dry/types/constructor.rb, line 78 def call_safe(input) coerced = fn.(input) { |output = input| return yield(output) } type.call_safe(coerced) { |output = coerced| yield(output) } end
@return [Object]
@api private
# File lib/dry/types/constructor.rb, line 86 def call_unsafe(input) type.call_unsafe(fn.(input)) end
@return [Class]
@api private
# File lib/dry/types/constructor.rb, line 130 def constrained_type Constrained::Coercible end
Build a new constructor by appending a block to the coercion function
@param [#call, nil] new_fn @param [Hash] options @param [#call, nil] block
@return [Constructor]
@api public
# File lib/dry/types/constructor.rb, line 115 def constructor(new_fn = nil, **options, &block) next_fn = Function[new_fn || block] if next_fn.wrapper? self.class.wrapper_type.new(with(**options), fn: next_fn) else with(**options, fn: fn >> next_fn) end end
Build a lax type
@return [Lax] @api public
# File lib/dry/types/constructor.rb, line 159 def lax Lax.new(constructor_type[type.lax, **options]) end
Build a new constructor by prepending a block to the coercion function
@param [#call, nil] new_fn @param [Hash] options @param [#call, nil] block
@return [Constructor]
@api public
# File lib/dry/types/constructor.rb, line 150 def prepend(new_fn = nil, **options, &block) with(**options, fn: fn << (new_fn || block)) end
@see Nominal#to_ast
@api public
# File lib/dry/types/constructor.rb, line 137 def to_ast(meta: true) [:constructor, [type.to_ast(meta: meta), fn.to_ast]] end
Wrap the type with a proc
@return [Proc]
@api public
# File lib/dry/types/constructor.rb, line 168 def to_proc proc { |value| self.(value) } end
@param [Object] input @param [#call,nil] block
@return [Logic::Result, Types::Result] @return [Object] if block given and try fails
@api public
# File lib/dry/types/constructor.rb, line 97 def try(input, &block) value = fn.(input) rescue CoercionError => e failure = failure(input, e) block_given? ? yield(failure) : failure else type.try(value, &block) end
Private Instance Methods
Delegates missing methods to {#type}
@param [Symbol] method @param [Array] args @param [#call, nil] block
@api private
# File lib/dry/types/constructor.rb, line 190 def method_missing(method, *args, &block) if type.respond_to?(method) response = type.public_send(method, *args, &block) if response.is_a?(Type) && type.class.equal?(response.class) response.constructor_type[response, **options] else response end else super end end
@param [Symbol] meth @param [Boolean] include_private @return [Boolean]
@api private
# File lib/dry/types/constructor.rb, line 179 def respond_to_missing?(meth, include_private = false) super || type.respond_to?(meth) end