dry-rb / dry-schema

Coercion and validation for data structures
https://dry-rb.org/gems/dry-schema
MIT License
424 stars 110 forks source link

Error output discards useful information from Enum types #469

Open paul opened 1 year ago

paul commented 1 year ago

Describe the bug

When using an Enum type with a schema, the output about the allowed values gets lost, and the error is reduced to "must be a string"

To Reproduce

module Types
  include Dry.Types()

  Status = Types::String.enum(
    "Queued" => 0,
    "Scheduled" => 1
  )
end

MySchema = Dry::Schema.Params do
  required(:status).filled(Types::Status)
end

class MyStruct < Dry::Struct
  attribute :status, Types::Status
end
Types::Status[0]
# => "Queued"
Types::Status[42]
# => Dry::Types::ConstraintError
# 42 violates constraints (type?(String, 42) AND included_in?(["Queued", "Scheduled"], 42) failed) 

bad_data = {status: 42}
MyStruct.new(bad_data)
# => Dry::Struct::Error [MyStruct.new] 
# 42 (Integer) has invalid type for :status violates constraints (type?(String, 42) AND included_in?(["Queued", "Scheduled"], 42) failed)>

MySchema.call(bad_data)
# => #<Dry::Schema::Result{:status=>42} errors={:status=>["must be a string"]} path=[]>

"status must be a string" isn't really true, and is misleading to what the problem really the (the value isn't one of the acceptable values for the enum)

Expected behavior

It would be nice if the error output for the enum had a better description of what was wrong. Something like "must be one of String Enum["Queued" => 0|"Scheduled" => 1]"

My environment