diff --git a/.yardopts b/.yardopts index 519741b..85a2bab 100644 --- a/.yardopts +++ b/.yardopts @@ -1,8 +1,8 @@ --title 'dry-types' --query '@api.text != "private"' --embed-mixins --o doc --r README.md +--output doc +--readme README.md --files CHANGELOG.md --markup markdown --markup-provider=redcarpet diff --git a/lib/dry/types.rb b/lib/dry/types.rb index 358cb56..bd71166 100644 --- a/lib/dry/types.rb +++ b/lib/dry/types.rb @@ -24,6 +24,9 @@ require 'dry/types/module' require 'dry/types/errors' module Dry + # Main library namespace + # + # @api public module Types extend Dry::Core::Extensions extend Dry::Core::ClassAttributes @@ -45,20 +48,32 @@ module Dry raise RuntimeError, "Import Dry.Types, not Dry::Types" end + # Return container with registered built-in type objects + # # @return [Container{String => Nominal}] + # + # @api private def self.container @container ||= Container.new end + # Check if a give type is registered + # + # @return [Boolean] + # # @api private def self.registered?(class_or_identifier) container.key?(identifier(class_or_identifier)) end + # Register a new built-in type + # # @param [String] name # @param [Type] type # @param [#call,nil] block + # # @return [Container{String => Nominal}] + # # @api private def self.register(name, type = nil, &block) container.register(name, type || block.call) @@ -67,7 +82,10 @@ module Dry # Get a built-in type by its name # # @param [String,Class] name + # # @return [Type,Class] + # + # @api public def self.[](name) type_map.fetch_or_store(name) do case name @@ -92,19 +110,29 @@ module Dry end end + # Infer a type identifier from the provided class + # # @param [#to_s] klass + # # @return [String] def self.identifier(klass) Inflector.underscore(klass).tr('/', '.') end + # Cached type map + # # @return [Concurrent::Map] + # + # @api private def self.type_map @type_map ||= Concurrent::Map.new end - # List of type keys defined in {Dry::Types.container} - # @return [] + # List of type keys defined in {Dry::Types.container} + # + # @return [String] + # + # @api private def self.type_keys container.keys end @@ -166,12 +194,18 @@ module Dry # @param [Array] namespaces List of type namespaces to export # @param [Symbol] default Default namespace to export # @param [Hash{Symbol => Symbol}] aliases Optional renamings, like strict: :Draconian + # # @return [Dry::Types::Module] # - # @see Dry::types::Module + # @see Dry::Types::Module + # + # @api public + # + # rubocop:disable Naming/MethodName def self.Types(*namespaces, default: Types::Undefined, **aliases) Types::Module.new(Types.container, *namespaces, default: default, **aliases) end + # rubocop:enable Naming/MethodName end require 'dry/types/core' # load built-in types diff --git a/lib/dry/types/any.rb b/lib/dry/types/any.rb index c9c0c17..14a3647 100644 --- a/lib/dry/types/any.rb +++ b/lib/dry/types/any.rb @@ -2,27 +2,41 @@ module Dry module Types + # Any is a nominal type that defines Object as the primitive class + # + # This type is useful in places where you can't be specific about the type + # and anything is acceptable. + # + # @api public class AnyClass < Nominal def self.name 'Any' end + # @api private def initialize(**options) super(::Object, options) end # @return [String] + # + # @api public def name 'Any' end # @param [Hash] new_options + # # @return [Type] + # + # @api public def with(new_options) self.class.new(**options, meta: @meta, **new_options) end # @return [Array] + # + # @api public def to_ast(meta: true) [:any, meta ? self.meta : EMPTY_HASH] end diff --git a/lib/dry/types/array.rb b/lib/dry/types/array.rb index 6715dd4..cd1da0e 100644 --- a/lib/dry/types/array.rb +++ b/lib/dry/types/array.rb @@ -4,9 +4,17 @@ require 'dry/types/array/member' module Dry module Types + # Array type can be used to define an array with optional member type + # + # @api public class Array < Nominal - # @param [Type] type + # Build an array type with a member type + # + # @param [Type,#call] type + # # @return [Array::Member] + # + # @api public def of(type) member = case type diff --git a/lib/dry/types/array/member.rb b/lib/dry/types/array/member.rb index 91b44c1..bcbf79e 100644 --- a/lib/dry/types/array/member.rb +++ b/lib/dry/types/array/member.rb @@ -3,22 +3,29 @@ module Dry module Types class Array < Nominal + # Member arrays define their member type that is applied to each element + # + # @api public class Member < Array # @return [Type] attr_reader :member # @param [Class] primitive # @param [Hash] options + # # @option options [Type] :member + # + # @api private def initialize(primitive, options = {}) @member = options.fetch(:member) super end - # @api private - # # @param [Object] input + # # @return [Array] + # + # @api private def call_unsafe(input) if primitive?(input) input.each_with_object([]) do |el, output| @@ -31,10 +38,10 @@ module Dry end end - # @api private - # # @param [Object] input # @return [Array] + # + # @api private def call_safe(input) if primitive?(input) failed = false @@ -56,9 +63,13 @@ module Dry # @param [Array, Object] input # @param [#call,nil] block + # # @yieldparam [Failure] failure # @yieldreturn [Result] + # # @return [Result,Logic::Result] + # + # @api public def try(input, &block) if primitive?(input) output = [] @@ -84,11 +95,15 @@ module Dry # Build a lax type # # @return [Lax] + # + # @api public def lax Lax.new(Member.new(primitive, { **options, member: member.lax })) end # @see Nominal#to_ast + # + # @api public def to_ast(meta: true) if member.respond_to?(:to_ast) [:array, [member.to_ast(meta: meta), meta ? self.meta : EMPTY_HASH]] diff --git a/lib/dry/types/builder.rb b/lib/dry/types/builder.rb index c32c597..2903d9c 100644 --- a/lib/dry/types/builder.rb +++ b/lib/dry/types/builder.rb @@ -4,42 +4,69 @@ require 'dry/core/deprecations' module Dry module Types + # Common API for building types and composition + # + # @api public module Builder include Dry::Core::Constants # @return [Class] + # + # @api private def constrained_type Constrained end # @return [Class] + # + # @api private def constructor_type Constructor end + # Compose two types into a Sum type + # # @param [Type] other + # # @return [Sum, Sum::Constrained] + # + # @api private def |(other) klass = constrained? && other.constrained? ? Sum::Constrained : Sum klass.new(self, other) end + # Turn a type into an optional type + # # @return [Sum] + # + # @api public def optional Types['strict.nil'] | self end + # Turn a type into a constrained type + # # @param [Hash] options constraining rule (see {Types.Rule}) + # # @return [Constrained] + # + # @api public def constrained(options) constrained_type.new(self, rule: Types.Rule(options)) end + # Turn a type into a type with a default value + # # @param [Object] input # @param [Hash] options # @param [#call,nil] block + # # @raise [ConstraintError] + # # @return [Default] + # + # @api public def default(input = Undefined, options = EMPTY_HASH, &block) unless input.frozen? || options[:shared] where = Dry::Core::Deprecations::STACK.() @@ -62,8 +89,13 @@ module Dry end end + # Define an enum on top of the existing type + # # @param [Array] values + # # @return [Enum] + # + # @api public def enum(*values) mapping = if values.length == 1 && values[0].is_a?(::Hash) @@ -75,15 +107,25 @@ module Dry Enum.new(constrained(included_in: mapping.keys), mapping: mapping) end + # Turn a type into a lax type that will rescue from type-errors and + # return the original input + # # @return [Lax] + # + # @api public def lax Lax.new(self) end + # Define a constructor for the type + # # @param [#call,nil] constructor # @param [Hash] options # @param [#call,nil] block + # # @return [Constructor] + # + # @api public def constructor(constructor = nil, **options, &block) constructor_type.new(with(options), fn: constructor || block) end diff --git a/lib/dry/types/builder_methods.rb b/lib/dry/types/builder_methods.rb index f8ba1a8..0a750ce 100644 --- a/lib/dry/types/builder_methods.rb +++ b/lib/dry/types/builder_methods.rb @@ -2,6 +2,11 @@ module Dry module Types + # Common API for building type objects in a convenient way + # + # rubocop:disable Naming/MethodName + # + # @api public module BuilderMethods # @api private def included(base) @@ -10,7 +15,8 @@ module Dry end # Build an array type. - # It is a shortcut for Array.of + # + # Shortcut for Array#of. # # @example # Types::Strings = Types.Array(Types::String) diff --git a/lib/dry/types/coercions.rb b/lib/dry/types/coercions.rb index b780158..669a45c 100644 --- a/lib/dry/types/coercions.rb +++ b/lib/dry/types/coercions.rb @@ -2,12 +2,19 @@ module Dry module Types + # Common coercion functions used by the built-in `Params` and `JSON` types + # + # @api public module Coercions include Dry::Core::Constants # @param [String, Object] input - # @return [nil] if the input is an empty string - # @return [Object] otherwise the input object is returned + # + # @return [nil] if the input is an empty string or nil + # + # @raise CoercionError + # + # @api public def to_nil(input, &_block) if input.nil? || empty_str?(input) nil @@ -19,8 +26,12 @@ module Dry end # @param [#to_str, Object] input + # # @return [Date, Object] + # # @see Date.parse + # + # @api public def to_date(input, &block) if input.respond_to?(:to_str) begin @@ -36,8 +47,12 @@ module Dry end # @param [#to_str, Object] input + # # @return [DateTime, Object] + # # @see DateTime.parse + # + # @api public def to_date_time(input, &block) if input.respond_to?(:to_str) begin @@ -53,8 +68,12 @@ module Dry end # @param [#to_str, Object] input + # # @return [Time, Object] + # # @see Time.parse + # + # @api public def to_time(input, &block) if input.respond_to?(:to_str) begin @@ -72,8 +91,12 @@ module Dry private # Checks whether String is empty + # # @param [String, Object] value + # # @return [Boolean] + # + # @api private def empty_str?(value) EMPTY_STRING.eql?(value) end diff --git a/lib/dry/types/coercions/json.rb b/lib/dry/types/coercions/json.rb index a90e289..50194e3 100644 --- a/lib/dry/types/coercions/json.rb +++ b/lib/dry/types/coercions/json.rb @@ -8,11 +8,19 @@ require 'time' module Dry module Types module Coercions + # JSON-specific coercions + # + # @api public module JSON extend Coercions # @param [#to_d, Object] input + # # @return [BigDecimal,nil] + # + # @raise CoercionError + # + # @api public def self.to_decimal(input, &block) if input.is_a?(::Float) input.to_d diff --git a/lib/dry/types/coercions/params.rb b/lib/dry/types/coercions/params.rb index 62fe46c..b30bf21 100644 --- a/lib/dry/types/coercions/params.rb +++ b/lib/dry/types/coercions/params.rb @@ -6,6 +6,9 @@ require 'bigdecimal/util' module Dry module Types module Coercions + # Params-specific coercions + # + # @api public module Params TRUE_VALUES = %w[1 on On ON t true True TRUE T y yes Yes YES Y].freeze FALSE_VALUES = %w[0 off Off OFF f false False FALSE F n no No NO N].freeze @@ -16,9 +19,15 @@ module Dry extend Coercions # @param [String, Object] input + # # @return [Boolean,Object] + # # @see TRUE_VALUES # @see FALSE_VALUES + # + # @raise CoercionError + # + # @api public def self.to_true(input, &_block) BOOLEAN_MAP.fetch(input.to_s) do if block_given? @@ -30,9 +39,15 @@ module Dry end # @param [String, Object] input + # # @return [Boolean,Object] + # # @see TRUE_VALUES # @see FALSE_VALUES + # + # @raise CoercionError + # + # @api public def self.to_false(input, &_block) BOOLEAN_MAP.fetch(input.to_s) do if block_given? @@ -44,7 +59,12 @@ module Dry end # @param [#to_int, #to_i, Object] input + # # @return [Integer, nil, Object] + # + # @raise CoercionError + # + # @api public def self.to_int(input, &block) if input.is_a? String Integer(input, 10) @@ -56,7 +76,12 @@ module Dry end # @param [#to_f, Object] input + # # @return [Float, nil, Object] + # + # @raise CoercionError + # + # @api public def self.to_float(input, &block) Float(input) rescue ArgumentError, TypeError => error @@ -64,7 +89,12 @@ module Dry end # @param [#to_d, Object] input + # # @return [BigDecimal, nil, Object] + # + # @raise CoercionError + # + # @api public def self.to_decimal(input, &block) to_float(input) do if block_given? @@ -78,7 +108,12 @@ module Dry end # @param [Array, String, Object] input + # # @return [Array, Object] + # + # @raise CoercionError + # + # @api public def self.to_ary(input, &_block) if empty_str?(input) [] @@ -92,7 +127,12 @@ module Dry end # @param [Hash, String, Object] input + # # @return [Hash, Object] + # + # @raise CoercionError + # + # @api public def self.to_hash(input, &_block) if empty_str?(input) {} diff --git a/lib/dry/types/constrained.rb b/lib/dry/types/constrained.rb index 76ccc78..dd6aa06 100644 --- a/lib/dry/types/constrained.rb +++ b/lib/dry/types/constrained.rb @@ -6,6 +6,9 @@ require 'dry/types/constrained/coercible' module Dry module Types + # Constrained types apply rules to the input + # + # @api public class Constrained include Type include Decorator @@ -17,14 +20,20 @@ module Dry attr_reader :rule # @param [Type] type + # # @param [Hash] options + # + # @api public def initialize(type, options) super @rule = options.fetch(:rule) end # @api private + # # @return [Object] + # + # @api public def call_unsafe(input) result = rule.(input) @@ -36,7 +45,10 @@ module Dry end # @api private + # # @return [Object] + # + # @api public def call_safe(input, &block) if rule[input] type.call_safe(input, &block) @@ -59,6 +71,7 @@ module Dry # @yieldreturn [Object] # @return [Object] # + # @api public def try(input, &block) result = rule.(input) @@ -73,19 +86,28 @@ module Dry # @param [Hash] options # The options hash provided to {Types.Rule} and combined # using {&} with previous {#rule} + # # @return [Constrained] + # # @see Dry::Logic::Operators#and + # + # @api public def constrained(options) with(rule: rule & Types.Rule(options)) end # @return [true] + # + # @api public def constrained? true end # @param [Object] value + # # @return [Boolean] + # + # @api public def ===(value) valid?(value) end @@ -93,11 +115,13 @@ module Dry # Build lax type. Constraints are not applicable to lax types hence unwrapping # # @return [Lax] + # @api public def lax type.lax end # @see Nominal#to_ast + # @api public def to_ast(meta: true) [:constrained, [type.to_ast(meta: meta), rule.to_ast]] end @@ -105,7 +129,10 @@ module Dry private # @param [Object] response + # # @return [Boolean] + # + # @api private def decorate?(response) super || response.is_a?(Constructor) end diff --git a/lib/dry/types/constrained/coercible.rb b/lib/dry/types/constrained/coercible.rb index 3077e05..7d06be9 100644 --- a/lib/dry/types/constrained/coercible.rb +++ b/lib/dry/types/constrained/coercible.rb @@ -3,9 +3,13 @@ module Dry module Types class Constrained + # Common coercion-related API for constrained types + # + # @api public class Coercible < Constrained - # @api private # @return [Object] + # + # @api private def call_unsafe(input) coerced = type.call_unsafe(input) result = rule.(coerced) @@ -17,8 +21,9 @@ module Dry end end - # @api private # @return [Object] + # + # @api private def call_safe(input) coerced = type.call_safe(input) { return yield } @@ -30,6 +35,8 @@ module Dry end # @see Dry::Types::Constrained#try + # + # @api public def try(input, &block) result = type.try(input) diff --git a/lib/dry/types/constraints.rb b/lib/dry/types/constraints.rb index b7a9fd8..705acc8 100644 --- a/lib/dry/types/constraints.rb +++ b/lib/dry/types/constraints.rb @@ -5,9 +5,15 @@ require 'dry/logic/predicates' require 'dry/logic/rule/predicate' module Dry + # Helper methods for constraint types + # + # @api public module Types # @param [Hash] options + # # @return [Dry::Logic::Rule] + # + # @api public def self.Rule(options) rule_compiler.( options.map { |key, val| @@ -19,6 +25,8 @@ module Dry end # @return [Dry::Logic::RuleCompiler] + # + # @api private def self.rule_compiler @rule_compiler ||= Logic::RuleCompiler.new(Logic::Predicates) end diff --git a/lib/dry/types/constructor.rb b/lib/dry/types/constructor.rb index 772e95a..81eee9d 100644 --- a/lib/dry/types/constructor.rb +++ b/lib/dry/types/constructor.rb @@ -5,6 +5,10 @@ require 'dry/types/constructor/function' module Dry module Types + # 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 class Constructor < Nominal include Dry::Equalizer(:type, :options, inspect: false) @@ -21,14 +25,20 @@ module Dry # @param [Builder, Object] input # @param [Hash] options # @param [#call, nil] block + # + # @api public 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 def initialize(type, fn: nil, **options) @type = type @fn = fn @@ -36,38 +46,53 @@ module Dry super(type, **options, fn: fn) end + # Return the inner type's primitive + # # @return [Class] + # + # @api public def primitive type.primitive end + # Return the inner type's name + # # @return [String] + # + # @api public def name type.name end # @return [Boolean] + # + # @api public def default? type.default? end - # @api private # @return [Object] + # + # @api private def call_safe(input) coerced = fn.(input) { return yield } type.call_safe(coerced) { |output = coerced| yield(output) } end - # @api private # @return [Object] + # + # @api private def call_unsafe(input) type.call_unsafe(fn.(input)) end # @param [Object] input # @param [#call,nil] block + # # @return [Logic::Result, Types::Result] # @return [Object] if block given and try fails + # + # @api public def try(input, &block) value = fn.(input) rescue CoercionError => error @@ -82,7 +107,10 @@ module Dry # @param [#call, nil] new_fn # @param [Hash] options # @param [#call, nil] block + # # @return [Constructor] + # + # @api public def constructor(new_fn = nil, **options, &block) with({**options, fn: fn >> (new_fn || block)}) end @@ -90,11 +118,15 @@ module Dry alias_method :>>, :constructor # @return [Class] + # + # @api private def constrained_type Constrained::Coercible end # @see Nominal#to_ast + # + # @api public def to_ast(meta: true) [:constructor, [type.to_ast(meta: meta), fn.to_ast]] end @@ -104,7 +136,10 @@ module Dry # @param [#call, nil] new_fn # @param [Hash] options # @param [#call, nil] block + # # @return [Constructor] + # + # @api public def prepend(new_fn = nil, **options, &block) with({**options, fn: fn << (new_fn || block)}) end @@ -113,6 +148,7 @@ module Dry # Build a lax type # # @return [Lax] + # @api public def lax Lax.new(Constructor.new(type.lax, options)) end @@ -120,28 +156,30 @@ module Dry # Wrap the type with a proc # # @return [Proc] + # + # @api public def to_proc proc { |value| self.(value) } end private - # @api private - # # @param [Symbol] meth # @param [Boolean] include_private # @return [Boolean] + # + # @api private def respond_to_missing?(meth, include_private = false) super || type.respond_to?(meth) end # Delegates missing methods to {#type} # - # @api private - # # @param [Symbol] method # @param [Array] args # @param [#call, nil] block + # + # @api private def method_missing(method, *args, &block) if type.respond_to?(method) response = type.__send__(method, *args, &block) diff --git a/lib/dry/types/constructor/function.rb b/lib/dry/types/constructor/function.rb index 7dd56f2..cc005ed 100644 --- a/lib/dry/types/constructor/function.rb +++ b/lib/dry/types/constructor/function.rb @@ -6,9 +6,10 @@ require 'concurrent/map' module Dry module Types class Constructor < Nominal + # Function is used internally by Constructor types + # # @api private class Function - # Wrapper for unsafe coercion functions # # @api private diff --git a/lib/dry/types/container.rb b/lib/dry/types/container.rb index 79926e0..f9938ea 100644 --- a/lib/dry/types/container.rb +++ b/lib/dry/types/container.rb @@ -4,6 +4,9 @@ require 'dry/container' module Dry module Types + # Internal container for the built-in types + # + # @api private class Container include Dry::Container::Mixin end diff --git a/lib/dry/types/decorator.rb b/lib/dry/types/decorator.rb index 22d68be..6a12152 100644 --- a/lib/dry/types/decorator.rb +++ b/lib/dry/types/decorator.rb @@ -4,6 +4,9 @@ require 'dry/types/options' module Dry module Types + # Common API for types + # + # @api public module Decorator include Options @@ -18,30 +21,42 @@ module Dry # @param [Object] input # @param [#call, nil] block + # # @return [Result,Logic::Result] # @return [Object] if block given and try fails + # + # @api public def try(input, &block) type.try(input, &block) end # @return [Boolean] + # + # @api public def default? type.default? end # @return [Boolean] + # + # @api public def constrained? type.constrained? end # @return [Sum] + # + # @api public def optional Types['strict.nil'] | self end # @param [Symbol] meth # @param [Boolean] include_private + # # @return [Boolean] + # + # @api public def respond_to_missing?(meth, include_private = false) super || type.respond_to?(meth) end @@ -49,6 +64,8 @@ module Dry # Wrap the type with a proc # # @return [Proc] + # + # @api public def to_proc proc { |value| self.(value) } end @@ -56,15 +73,21 @@ module Dry private # @param [Object] response + # # @return [Boolean] + # + # @api private def decorate?(response) response.is_a?(type.class) end # Delegates missing methods to {#type} + # # @param [Symbol] meth # @param [Array] args # @param [#call, nil] block + # + # @api private def method_missing(meth, *args, &block) if type.respond_to?(meth) response = type.__send__(meth, *args, &block) @@ -80,6 +103,8 @@ module Dry end # Replace underlying type + # + # @api private def __new__(type) self.class.new(type, *@__args__[1..-1], **@options) end diff --git a/lib/dry/types/default.rb b/lib/dry/types/default.rb index 175fece..4106da1 100644 --- a/lib/dry/types/default.rb +++ b/lib/dry/types/default.rb @@ -4,7 +4,11 @@ require 'dry/types/decorator' module Dry module Types + # Default types are useful when a missing value should be replaced by a default one + # + # @api public class Default + # @api private class Callable < Default include Dry::Equalizer(:type, inspect: false) @@ -27,7 +31,10 @@ module Dry alias_method :evaluate, :value # @param [Object, #call] value + # # @return [Class] {Default} or {Default::Callable} + # + # @api private def self.[](value) if value.respond_to?(:call) Callable @@ -38,37 +45,52 @@ module Dry # @param [Type] type # @param [Object] value + # + # @api private def initialize(type, value, **options) super @value = value end + # Build a constrained type + # # @param [Array] args see {Dry::Types::Builder#constrained} + # # @return [Default] + # + # @api public def constrained(*args) type.constrained(*args).default(value) end # @return [true] + # + # @api public def default? true end # @param [Object] input + # # @return [Result::Success] + # + # @api public def try(input) success(call(input)) end # @return [Boolean] + # + # @api public def valid?(value = Undefined) Undefined.equal?(value) || super end - # @api private - # # @param [Object] input + # # @return [Object] value passed through {#type} or {#default} value + # + # @api private def call_unsafe(input = Undefined) if input.equal?(Undefined) evaluate @@ -77,10 +99,11 @@ module Dry end end - # @api pribate - # # @param [Object] input + # # @return [Object] value passed through {#type} or {#default} value + # + # @api private def call_safe(input = Undefined, &block) if input.equal?(Undefined) evaluate diff --git a/lib/dry/types/enum.rb b/lib/dry/types/enum.rb index a6ccaf9..f945739 100644 --- a/lib/dry/types/enum.rb +++ b/lib/dry/types/enum.rb @@ -4,6 +4,9 @@ require 'dry/types/decorator' module Dry module Types + # Enum types can be used to define an enum on top of an existing type + # + # @api public class Enum include Type include Dry::Equalizer(:type, :mapping, inspect: false) @@ -21,6 +24,8 @@ module Dry # @param [Type] type # @param [Hash] options # @option options [Array] :values + # + # @api private def initialize(type, options) super @mapping = options.fetch(:mapping).freeze @@ -29,23 +34,28 @@ module Dry freeze end - # @api private # @return [Object] + # + # @api private def call_unsafe(input) type.call_unsafe(map_value(input)) end - # @api private # @return [Object] + # + # @api private def call_safe(input, &block) type.call_safe(map_value(input), &block) end # @see Dry::Types::Constrained#try + # + # @api public def try(input) super(map_value(input)) end + # @api private def default(*) raise '.enum(*values).default(value) is not supported. Call '\ '.default(value).enum(*values) instead' @@ -55,11 +65,15 @@ module Dry alias_method :include?, :valid? # @see Nominal#to_ast + # + # @api public def to_ast(meta: true) [:enum, [type.to_ast(meta: meta), mapping]] end # @return [String] + # + # @api public def to_s PRINTER.(self) end @@ -69,10 +83,11 @@ module Dry # Maps a value # - # @api private - # # @param [Object] input + # # @return [Object] + # + # @api private def map_value(input) if input.equal?(Undefined) type.call diff --git a/lib/dry/types/extensions/maybe.rb b/lib/dry/types/extensions/maybe.rb index 80a453e..955fad7 100644 --- a/lib/dry/types/extensions/maybe.rb +++ b/lib/dry/types/extensions/maybe.rb @@ -5,6 +5,9 @@ require 'dry/types/decorator' module Dry module Types + # Maybe extension provides Maybe types where values are wrapped using `Either` monad + # + # @api public class Maybe include Type include Dry::Equalizer(:type, :options, inspect: false) @@ -13,10 +16,11 @@ module Dry include Printable include Dry::Monads::Maybe::Mixin - # @api private - # # @param [Dry::Monads::Maybe, Object] input + # # @return [Dry::Monads::Maybe] + # + # @api private def call_unsafe(input = Undefined) case input when Dry::Monads::Maybe @@ -28,10 +32,11 @@ module Dry end end - # @api private - # # @param [Dry::Monads::Maybe, Object] input + # # @return [Dry::Monads::Maybe] + # + # @api private def call_safe(input = Undefined, &block) case input when Dry::Monads::Maybe @@ -44,7 +49,10 @@ module Dry end # @param [Object] input + # # @return [Result::Success] + # + # @api public def try(input = Undefined) res = if input.equal?(Undefined) None() @@ -56,13 +64,19 @@ module Dry end # @return [true] + # + # @api public def default? true end # @param [Object] value + # # @see Dry::Types::Builder#default + # # @raise [ArgumentError] if nil provided as default value + # + # @api public def default(value) if value.nil? raise ArgumentError, "nil cannot be used as a default of a maybe type" @@ -73,15 +87,21 @@ module Dry end module Builder + # Turn a type into a maybe type + # # @return [Maybe] + # + # @api public def maybe Maybe.new(Types['strict.nil'] | self) end end + # @api private class Printer MAPPING[Maybe] = :visit_maybe + # @api private def visit_maybe(maybe) visit(maybe.type) do |type| yield "Maybe<#{type}>" diff --git a/lib/dry/types/fn_container.rb b/lib/dry/types/fn_container.rb index 6d8e20e..f233ad4 100644 --- a/lib/dry/types/fn_container.rb +++ b/lib/dry/types/fn_container.rb @@ -4,6 +4,9 @@ require 'dry/types/container' module Dry module Types + # Internal container for constructor functions used by the built-in types + # + # @api private class FnContainer # @api private def self.container diff --git a/lib/dry/types/hash.rb b/lib/dry/types/hash.rb index 62d2bd4..c256f33 100644 --- a/lib/dry/types/hash.rb +++ b/lib/dry/types/hash.rb @@ -4,10 +4,13 @@ require 'dry/types/hash/constructor' module Dry module Types + # Hash types can be used to define maps and schemas + # + # @api public class Hash < Nominal NOT_REQUIRED = { required: false }.freeze - # @overload schmea(type_map, meta = EMPTY_HASH) + # @overload schema(type_map, meta = EMPTY_HASH) # @param [{Symbol => Dry::Types::Nominal}] type_map # @param [Hash] meta # @return [Dry::Types::Schema] @@ -16,6 +19,8 @@ module Dry # @param [Array] key List of schema keys # @param [Hash] meta # @return [Dry::Types::Schema] + # + # @api public def schema(keys_or_map, meta = EMPTY_HASH) if keys_or_map.is_a?(::Array) keys = keys_or_map @@ -30,7 +35,10 @@ module Dry # # @param [Type] key_type # @param [Type] value_type + # # @return [Map] + # + # @api public def map(key_type, value_type) Map.new( primitive, @@ -51,9 +59,13 @@ module Dry alias_method :symbolized, :weak # Injects a type transformation function for building schemas + # # @param [#call,nil] proc # @param [#call,nil] block + # # @return [Hash] + # + # @api public def with_type_transform(proc = nil, &block) fn = proc || block @@ -73,12 +85,17 @@ module Dry # Whether the type transforms types of schemas created by {Dry::Types::Hash#schema} # # @return [Boolean] + # + # @api public def transform_types? !options[:type_transform_fn].nil? end # @param meta [Boolean] Whether to dump the meta to the AST + # # @return [Array] An AST representation + # + # @api public def to_ast(meta: true) if RUBY_VERSION >= "2.5" opts = options.slice(:type_transform_fn) diff --git a/lib/dry/types/hash/constructor.rb b/lib/dry/types/hash/constructor.rb index 214742b..3efe7e6 100644 --- a/lib/dry/types/hash/constructor.rb +++ b/lib/dry/types/hash/constructor.rb @@ -4,6 +4,9 @@ require 'dry/types/constructor' module Dry module Types + # Hash type exposes additional APIs for working with schema hashes + # + # @api public class Hash < Nominal class Constructor < ::Dry::Types::Constructor # @api private @@ -12,6 +15,8 @@ module Dry end # @return [Lax] + # + # @api public def lax type.lax.constructor(fn, meta: meta) end diff --git a/lib/dry/types/lax.rb b/lib/dry/types/lax.rb index 6bc0a26..08bcc7f 100644 --- a/lib/dry/types/lax.rb +++ b/lib/dry/types/lax.rb @@ -5,6 +5,9 @@ require 'dry/types/decorator' module Dry module Types + # Lax types rescue from type-related errors when constructors fail + # + # @api public class Lax include Type include Decorator @@ -15,7 +18,10 @@ module Dry private :options, :constructor # @param [Object] input + # # @return [Object] + # + # @api public def call(input) type.call_safe(input) { |output = input| output } end @@ -25,9 +31,13 @@ module Dry # @param [Object] input # @param [#call,nil] block + # # @yieldparam [Failure] failure # @yieldreturn [Result] + # # @return [Result,Logic::Result] + # + # @api public def try(input, &block) type.try(input, &block) rescue CoercionError => error @@ -36,11 +46,15 @@ module Dry end # @see Nominal#to_ast + # + # @api public def to_ast(meta: true) [:lax, type.to_ast(meta: meta)] end # @return [Lax] + # + # @api public def lax self end @@ -48,7 +62,10 @@ module Dry private # @param [Object, Dry::Types::Constructor] response + # # @return [Boolean] + # + # @api private def decorate?(response) super || response.is_a?(constructor_type) end diff --git a/lib/dry/types/map.rb b/lib/dry/types/map.rb index 9db759e..077f382 100644 --- a/lib/dry/types/map.rb +++ b/lib/dry/types/map.rb @@ -9,34 +9,48 @@ module Dry # Dry::Types['integer'].constrained(gteq: 1, lteq: 10), # Dry::Types['string'] # ) + # # type.(1 => 'right') # # => {1 => 'right'} + # # type.('1' => 'wrong') # # Dry::Types::MapError: "1" violates constraints (type?(Integer, "1") AND gteq?(1, "1") AND lteq?(10, "1") failed) + # # type.(11 => 'wrong') # # Dry::Types::MapError: 11 violates constraints (lteq?(10, 11) failed) + # + # @api public class Map < Nominal def initialize(_primitive, key_type: Types['any'], value_type: Types['any'], meta: EMPTY_HASH) super(_primitive, key_type: key_type, value_type: value_type, meta: meta) end # @return [Type] + # + # @api public def key_type options[:key_type] end # @return [Type] + # + # @api public def value_type options[:value_type] end # @return [String] + # + # @api public def name 'Map' end # @param [Hash] hash + # # @return [Hash] + # + # @api private def call_unsafe(hash) try(hash) { |failure| raise MapError, failure.error.message @@ -44,13 +58,19 @@ module Dry end # @param [Hash] hash + # # @return [Hash] + # + # @api private def call_safe(hash) try(hash) { return yield }.input end # @param [Hash] hash + # # @return [Result] + # + # @api public def try(hash) result = coerce(hash) return result if result.success? || !block_given? @@ -58,7 +78,10 @@ module Dry end # @param meta [Boolean] Whether to dump the meta to the AST + # # @return [Array] An AST representation + # + # @api public def to_ast(meta: true) [:map, [key_type.to_ast(meta: true), @@ -67,6 +90,8 @@ module Dry end # @return [Boolean] + # + # @api public def constrained? value_type.constrained? end diff --git a/lib/dry/types/meta.rb b/lib/dry/types/meta.rb index f9884c3..31578cf 100644 --- a/lib/dry/types/meta.rb +++ b/lib/dry/types/meta.rb @@ -2,6 +2,9 @@ module Dry module Types + # Storage for meta-data + # + # @api public module Meta def initialize(*args, meta: EMPTY_HASH, **options) super(*args, **options) @@ -9,7 +12,10 @@ module Dry end # @param [Hash] new_options + # # @return [Type] + # + # @api public def with(options) super(meta: @meta, **options) end @@ -20,6 +26,8 @@ module Dry # @overload meta(data) # @param [Hash] new metadata to merge into existing metadata # @return [Type] new type with added metadata + # + # @api public def meta(data = nil) if !data @meta @@ -31,7 +39,10 @@ module Dry end # Resets meta + # # @return [Dry::Types::Type] + # + # @api public def pristine with(meta: EMPTY_HASH) end diff --git a/lib/dry/types/module.rb b/lib/dry/types/module.rb index 4e45818..e0296fd 100644 --- a/lib/dry/types/module.rb +++ b/lib/dry/types/module.rb @@ -10,10 +10,13 @@ module Dry # module Types # include Dry::Types(:strict, :coercible, :nominal, default: :strict) # end - # # Types.constants + # + # Types.constants # # => [:Class, :Strict, :Symbol, :Integer, :Float, :String, :Array, :Hash, # # :Decimal, :Nil, :True, :False, :Bool, :Date, :Nominal, :DateTime, :Range, # # :Coercible, :Time] + # + # @api public class Module < ::Module def initialize(registry, *args) @registry = registry diff --git a/lib/dry/types/nominal.rb b/lib/dry/types/nominal.rb index df6d517..6ca73a4 100644 --- a/lib/dry/types/nominal.rb +++ b/lib/dry/types/nominal.rb @@ -8,6 +8,11 @@ require 'dry/types/meta' module Dry module Types + # Nominal types define a primitive class and do not apply any constructors or constraints + # + # Use these types for annotations and the base for building more complex types on top of them. + # + # @api public class Nominal include Type include Options @@ -20,7 +25,10 @@ module Dry attr_reader :primitive # @param [Class] primitive + # # @return [Type] + # + # @api private def self.[](primitive) if primitive == ::Array Types::Array @@ -35,6 +43,8 @@ module Dry # @param [Type,Class] primitive # @param [Hash] options + # + # @api private def initialize(primitive, **options) super @primitive = primitive @@ -42,55 +52,79 @@ module Dry end # @return [String] + # + # @api public def name primitive.name end # @return [false] + # + # @api public def default? false end # @return [false] + # + # @api public def constrained? false end # @return [false] + # + # @api public def optional? false end # @param [BasicObject] input + # # @return [BasicObject] + # + # @api private def call_unsafe(input) input end # @param [BasicObject] input + # # @return [BasicObject] + # + # @api private def call_safe(input) input end # @param [Object] input # @param [#call,nil] block + # # @yieldparam [Failure] failure # @yieldreturn [Result] + # # @return [Result,Logic::Result] when a block is not provided # @return [nil] otherwise + # + # @api public def try(input) success(input) end # @param (see Dry::Types::Success#initialize) + # # @return [Result::Success] + # + # @api public def success(input) Result::Success.new(input) end # @param (see Failure#initialize) + # # @return [Result::Failure] + # + # @api public def failure(input, error) unless error.is_a?(CoercionError) raise ArgumentError, "error must be a CoercionError" @@ -99,12 +133,17 @@ module Dry end # Checks whether value is of a #primitive class + # # @param [Object] value + # # @return [Boolean] + # + # @api public def primitive?(value) value.is_a?(primitive) end + # @api private def coerce(input, &_block) if primitive?(input) input @@ -115,6 +154,7 @@ module Dry end end + # @api private def try_coerce(input) result = success(input) @@ -135,6 +175,8 @@ module Dry # Return AST representation of a type nominal # # @return [Array] + # + # @api public def to_ast(meta: true) [:nominal, [primitive, meta ? self.meta : EMPTY_HASH]] end @@ -142,6 +184,8 @@ module Dry # Return self. Nominal types are lax by definition # # @return [Nominal] + # + # @api public def lax self end @@ -149,6 +193,8 @@ module Dry # Wrap the type with a proc # # @return [Proc] + # + # @api public def to_proc ALWAYS end diff --git a/lib/dry/types/options.rb b/lib/dry/types/options.rb index 1ea454b..090b3f6 100644 --- a/lib/dry/types/options.rb +++ b/lib/dry/types/options.rb @@ -2,18 +2,26 @@ module Dry module Types + # Common API for types with options + # + # @api private module Options # @return [Hash] attr_reader :options # @see Nominal#initialize + # + # @api private def initialize(*args, **options) @__args__ = args.freeze @options = options.freeze end # @param [Hash] new_options + # # @return [Type] + # + # @api private def with(**new_options) self.class.new(*@__args__, **options, **new_options) end diff --git a/lib/dry/types/printable.rb b/lib/dry/types/printable.rb index 59c898f..3021882 100644 --- a/lib/dry/types/printable.rb +++ b/lib/dry/types/printable.rb @@ -2,8 +2,11 @@ module Dry module Types + # @api private module Printable # @return [String] + # + # @api private def to_s PRINTER.(self) { super } end diff --git a/lib/dry/types/result.rb b/lib/dry/types/result.rb index 33b65f4..4e0d5b3 100644 --- a/lib/dry/types/result.rb +++ b/lib/dry/types/result.rb @@ -4,6 +4,9 @@ require 'dry/equalizer' module Dry module Types + # Result class used by {Type#try} + # + # @api public class Result include Dry::Equalizer(:input, inspect: false) @@ -11,22 +14,34 @@ module Dry attr_reader :input # @param [Object] input + # + # @api private def initialize(input) @input = input end + # Success result + # + # @api public class Success < Result # @return [true] + # + # @api public def success? true end # @return [false] + # + # @api public def failure? false end end + # Failure result + # + # @api public class Failure < Result include Dry::Equalizer(:input, :error, inspect: false) @@ -34,23 +49,32 @@ module Dry attr_reader :error # @param [Object] input + # # @param [#to_s] error + # + # @api private def initialize(input, error) super(input) @error = error end # @return [String] + # + # @api private def to_s error.to_s end # @return [false] + # + # @api public def success? false end # @return [true] + # + # @api public def failure? true end diff --git a/lib/dry/types/schema.rb b/lib/dry/types/schema.rb index 82b1d92..1f4a7f8 100644 --- a/lib/dry/types/schema.rb +++ b/lib/dry/types/schema.rb @@ -16,6 +16,8 @@ module Dry # @see Dry::Types::Default::Callable#evaluate # # {Schema} implements Enumerable using its keys as collection. + # + # @api public class Schema < Hash NO_TRANSFORM = Dry::Types::FnContainer.register { |x| x } SYMBOLIZE_KEY = Dry::Types::FnContainer.register(:to_sym.to_proc) @@ -33,8 +35,11 @@ module Dry # @param [Class] _primitive # @param [Hash] options + # # @option options [Array[Dry::Types::Schema::Key]] :keys # @option options [String] :key_transform_fn + # + # @api private def initialize(_primitive, **options) @keys = options.fetch(:keys) @name_key_map = keys.each_with_object({}) do |key, idx| @@ -49,31 +54,44 @@ module Dry end # @param [Hash] hash + # # @return [Hash{Symbol => Object}] + # + # @api private def call_unsafe(hash, options = EMPTY_HASH) resolve_unsafe(coerce(hash), options) end # @param [Hash] hash + # # @return [Hash{Symbol => Object}] + # + # @api private def call_safe(hash, options = EMPTY_HASH) resolve_safe(coerce(hash) { return yield }, options) { return yield } end # @param [Hash] hash + # # @option options [Boolean] :skip_missing If true don't raise error if on missing keys # @option options [Boolean] :resolve_defaults If false default value # won't be evaluated for missing key # @return [Hash{Symbol => Object}] + # + # @api public def apply(hash, options = EMPTY_HASH) call_unsafe(hash, options) end # @param [Hash] hash + # # @yieldparam [Failure] failure # @yieldreturn [Result] + # # @return [Logic::Result] # @return [Object] if coercion fails and a block is given + # + # @api public def try(input) if primitive?(input) success = true @@ -122,7 +140,10 @@ module Dry end # @param meta [Boolean] Whether to dump the meta to the AST + # # @return [Array] An AST representation + # + # @api public def to_ast(meta: true) if RUBY_VERSION >= "2.5" opts = options.slice(:key_transform_fn, :type_transform_fn, :strict) @@ -141,21 +162,31 @@ module Dry end # Whether the schema rejects unknown keys + # # @return [Boolean] + # + # @api public def strict? options.fetch(:strict, false) end # Make the schema intolerant to unknown keys + # # @return [Schema] + # + # @api public def strict with(strict: true) end # Injects a key transformation function + # # @param [#call,nil] proc # @param [#call,nil] block + # # @return [Schema] + # + # @api public def with_key_transform(proc = nil, &block) fn = proc || block @@ -170,6 +201,8 @@ module Dry # Whether the schema transforms input keys # # @return [Boolean] + # + # @api public def trasform_keys? !options[:key_transform_fn].nil? end @@ -178,10 +211,13 @@ module Dry # @param [{Symbol => Dry::Types::Nominal}] type_map # @param [Hash] meta # @return [Dry::Types::Schema] + # # @overload schema(keys) # @param [Array] key List of schema keys # @param [Hash] meta # @return [Dry::Types::Schema] + # + # @api public def schema(keys_or_map) if keys_or_map.is_a?(::Array) new_keys = keys_or_map @@ -196,6 +232,8 @@ module Dry # Iterate over each key type # # @return [Array,Enumerator] + # + # @api public def each(&block) keys.each(&block) end @@ -203,12 +241,16 @@ module Dry # Whether the schema has the given key # # @param [Symbol] name Key name + # # @return [Boolean] + # + # @api public def key?(name) name_key_map.key?(name) end - # Fetch key type by a key name. + # Fetch key type by a key name + # # Behaves as ::Hash#fetch # # @overload key(name, fallback = Undefined) @@ -220,6 +262,8 @@ module Dry # @param [Symbol] name Key name # @param [Proc] block Fallback block, runs if key is missing # @return [Dry::Types::Schema::Key,Object] key type or block value if key is not in schema + # + # @api public def key(name, fallback = Undefined, &block) if Undefined.equal?(fallback) name_key_map.fetch(name, &block) @@ -229,11 +273,15 @@ module Dry end # @return [Boolean] + # + # @api public def constrained? true end # @return [Lax] + # + # @api public def lax Lax.new(schema(keys.map(&:lax))) end @@ -242,9 +290,9 @@ module Dry # @param [Array] keys # - # @api private - # # @return [Dry::Types::Schema] + # + # @api private def merge_keys(*keys) keys. flatten(1). @@ -311,6 +359,8 @@ module Dry end # Try to add missing keys to the hash + # + # @api private def resolve_missing_keys(hash, options) skip_missing = options.fetch(:skip_missing, false) resolve_defaults = options.fetch(:resolve_defaults, true) @@ -331,13 +381,18 @@ module Dry end # @param hash_keys [Array] + # # @return [UnknownKeysError] + # + # @api private def unexpected_keys(hash_keys) extra_keys = hash_keys.map(&transform_key) - name_key_map.keys UnknownKeysError.new(extra_keys) end # @return [MissingKeyError] + # + # @api private def missing_key(key) MissingKeyError.new(key) end diff --git a/lib/dry/types/schema/key.rb b/lib/dry/types/schema/key.rb index 4247f2d..a37888d 100644 --- a/lib/dry/types/schema/key.rb +++ b/lib/dry/types/schema/key.rb @@ -4,6 +4,9 @@ require 'dry/equalizer' module Dry module Types + # Schema is a hash with explicit member types defined + # + # @api public class Schema < Hash # Proxy type for schema keys. Contains only key name and # whether it's required or not. All other calls deletaged @@ -30,15 +33,19 @@ module Dry @name = name end + # @api private def call_safe(input, &block) type.call_safe(input, &block) end + # @api private def call_unsafe(input) type.call_unsafe(input) end # @see Dry::Types::Nominal#try + # + # @api public def try(input, &block) type.try(input, &block) end @@ -46,6 +53,8 @@ module Dry # Whether the key is required in schema input # # @return [Boolean] + # + # @api public def required? options.fetch(:required) end @@ -60,6 +69,8 @@ module Dry # # @param [Boolean] required New value # @return [Dry::Types::Schema::Key] + # + # @api public def required(required = Undefined) if Undefined.equal?(required) options.fetch(:required) @@ -71,6 +82,8 @@ module Dry # Make key not required # # @return [Dry::Types::Schema::Key] + # + # @api public def omittable required(false) end @@ -78,6 +91,8 @@ module Dry # Turn key into a lax type. Lax types are not strict hence such keys are not required # # @return [Lax] + # + # @api public def lax super.required(false) end @@ -85,6 +100,8 @@ module Dry # Dump to internal AST representation # # @return [Array] + # + # @api public def to_ast(meta: true) [ :key, @@ -98,6 +115,7 @@ module Dry private + # @api private def decorate?(response) response.is_a?(Type) end diff --git a/lib/dry/types/sum.rb b/lib/dry/types/sum.rb index 5281575..9f4fdb3 100644 --- a/lib/dry/types/sum.rb +++ b/lib/dry/types/sum.rb @@ -5,6 +5,9 @@ require 'dry/types/meta' module Dry module Types + # Sum type + # + # @api public class Sum include Type include Builder @@ -19,6 +22,7 @@ module Dry # @return [Type] attr_reader :right + # @api private class Constrained < Sum # @return [Dry::Logic::Operations::Or] def rule @@ -34,6 +38,8 @@ module Dry # @param [Type] left # @param [Type] right # @param [Hash] options + # + # @api private def initialize(left, right, options = {}) super @left, @right = left, right @@ -41,37 +47,54 @@ module Dry end # @return [String] + # + # @api public def name [left, right].map(&:name).join(' | ') end # @return [false] + # + # @api public def default? false end # @return [false] + # + # @api public def constrained? false end # @return [Boolean] + # + # @api public def optional? primitive?(nil) end # @param [Object] input + # # @return [Object] + # + # @api private def call_unsafe(input) left.call_safe(input) { right.call_unsafe(input) } end # @param [Object] input + # # @return [Object] + # + # @api private def call_safe(input, &block) left.call_safe(input) { right.call_safe(input, &block) } end + # @param [Object] input + # + # @api public def try(input) left.try(input) do right.try(input) do |failure| @@ -84,6 +107,7 @@ module Dry end end + # @api private def success(input) if left.valid?(input) left.success(input) @@ -94,6 +118,7 @@ module Dry end end + # @api private def failure(input, _error = nil) if !left.valid?(input) left.failure(input, left.try(input).error) @@ -103,7 +128,10 @@ module Dry end # @param [Object] value + # # @return [Boolean] + # + # @api private def primitive?(value) left.primitive?(value) || right.primitive?(value) end @@ -112,6 +140,8 @@ module Dry # to the right branch # # @see [Meta#meta] + # + # @api public def meta(data = nil) if data.nil? optional? ? right.meta : super @@ -123,13 +153,19 @@ module Dry end # @see Nominal#to_ast + # + # @api public def to_ast(meta: true) [:sum, [left.to_ast(meta: meta), right.to_ast(meta: meta), meta ? self.meta : EMPTY_HASH]] end # @param [Hash] options + # # @return [Constrained,Sum] + # # @see Builder#constrained + # + # @api public def constrained(options) if optional? right.constrained(options).optional @@ -141,6 +177,8 @@ module Dry # Wrap the type with a proc # # @return [Proc] + # + # @api public def to_proc proc { |value| self.(value) } end diff --git a/lib/dry/types/type.rb b/lib/dry/types/type.rb index a24bbcd..5aeffcb 100644 --- a/lib/dry/types/type.rb +++ b/lib/dry/types/type.rb @@ -4,6 +4,9 @@ require 'dry/core/deprecations' module Dry module Types + # Common Type module denoting an object is a Type + # + # @api public module Type extend ::Dry::Core::Deprecations[:'dry-types'] @@ -12,6 +15,8 @@ module Dry # Whether a value is a valid member of the type # # @return [Boolean] + # + # @api private def valid?(input = Undefined) call_safe(input) { return false } true @@ -36,6 +41,7 @@ module Dry # @yieldparam [Object] output Partially coerced value # @return [Object] # + # @api public def call(input = Undefined, &block) if block_given? call_safe(input, &block) diff --git a/lib/dry/types/version.rb b/lib/dry/types/version.rb index 955a715..589e58a 100644 --- a/lib/dry/types/version.rb +++ b/lib/dry/types/version.rb @@ -2,6 +2,6 @@ module Dry module Types - VERSION = '1.0.0'.freeze + VERSION = '1.0.0' end end