lib/dry/types/coercions/params.rb
# frozen_string_literal: true
require "bigdecimal"
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
BOOLEAN_MAP = EMPTY_HASH.merge(
[true, *TRUE_VALUES].to_h { |v| [v, true] },
[false, *FALSE_VALUES].to_h { |v| [v, false] }
).freeze
extend Coercions
# @param [Object] input
#
# @return [nil] if the input is an empty string or nil
#
# @raise CoercionError
#
# @api public
def self.to_nil(input, &)
if input.nil? || empty_str?(input)
nil
elsif block_given?
yield
else
raise CoercionError, "#{input.inspect} is not nil"
end
end
# @param [String, Object] input
#
# @return [Boolean,Object]
#
# @see TRUE_VALUES
# @see FALSE_VALUES
#
# @raise CoercionError
#
# @api public
def self.to_true(input, &)
BOOLEAN_MAP.fetch(input.to_s) do
if block_given?
yield
else
raise CoercionError, "#{input} cannot be coerced to true"
end
end
end
# @param [String, Object] input
#
# @return [Boolean,Object]
#
# @see TRUE_VALUES
# @see FALSE_VALUES
#
# @raise CoercionError
#
# @api public
def self.to_false(input, &)
BOOLEAN_MAP.fetch(input.to_s) do
if block_given?
yield
else
raise CoercionError, "#{input} cannot be coerced to false"
end
end
end
# @param [#to_int, #to_i, Object] input
#
# @return [Integer, nil, Object]
#
# @raise CoercionError
#
# @api public
def self.to_int(input, &)
if input.is_a?(::String)
Integer(input, 10)
else
Integer(input)
end
rescue ::ArgumentError, ::TypeError => e
CoercionError.handle(e, &)
end
# @param [#to_f, Object] input
#
# @return [Float, nil, Object]
#
# @raise CoercionError
#
# @api public
def self.to_float(input, &)
Float(input)
rescue ::ArgumentError, ::TypeError => e
CoercionError.handle(e, &)
end
# @param [#to_d, Object] input
#
# @return [BigDecimal, nil, Object]
#
# @raise CoercionError
#
# @api public
def self.to_decimal(input, &)
to_float(input) do
if block_given?
return yield
else
raise CoercionError, "#{input.inspect} cannot be coerced to decimal"
end
end
input.to_d
end
# @param [Array, String, Object] input
#
# @return [Array, Object]
#
# @raise CoercionError
#
# @api public
def self.to_ary(input, &)
if empty_str?(input)
[]
elsif input.is_a?(::Array)
input
elsif block_given?
yield
else
raise CoercionError, "#{input.inspect} cannot be coerced to array"
end
end
# @param [Hash, String, Object] input
#
# @return [Hash, Object]
#
# @raise CoercionError
#
# @api public
def self.to_hash(input, &)
if empty_str?(input)
{}
elsif input.is_a?(::Hash)
input
elsif block_given?
yield
else
raise CoercionError, "#{input.inspect} cannot be coerced to hash"
end
end
end
end
end
end