Is it possible to define a schema such that a value is either a scalar or a hash with type coercion?
Here’s an example using dry-schema directly:
module Types
include Dry::Types()
HashType = Hash.schema(c: Params::Float)
SumHashParam = Params::Float | HashType
SumScalarParam = Params::Float | Params::Bool
end
ASchema = Dry::Schema.Params do
optional(:a).filled(Types::SumScalarParam)
end
assert_equal({ a: 1.0 }, ASchema.(a: "1.0").to_h) # Works!
assert_equal({ a: true }, ASchema.(a: "true").to_h) # Works!
BSchema = Dry::Schema.Params do
optional(:b).filled(Types::SumHashParam)
end
Evaluation of BSchema raises the following error:
undefined method `visit_schema' for #<Dry::Schema::PredicateInferrer::Compiler:0x000055f01c68db40>
Did you mean? visit_sum
(repl):24:in `block in <main>'
(repl):23:in `<main>'
In dry-validation, I was able to get this to work, but without type coercion on the scalar value:
class BValidation < Dry::Validation::Contract
params do
required(:b) do
float? | hash do
required(:c).filled(:float)
end
end
end
end
assert_equal({ b: 1.0 }, BValidation.new.({ b: 1.0 }).to_h)
assert_equal(
{ b: ["must be a float or must be a hash"] },
BValidation.new.({ b: "1.0" }).errors.to_h # no coercion on scalar
)
assert_equal({ b: { c: 1.0 } }, BValidation.new.({ b: { c: "1.0" } }).to_h)
Here’s a link to the code in a repl.it: https://repl.it/@ahacop/CheapQuarrelsomeApplicationserver