Constrained types not respected when validating schema


#1

Hi all,

Been starting to implement Dry::Types, which we reuse for simple things like email or URL pattern matching.

We started creating schemas for validating multiple attributes. However, we’ve found that when using custom types with schemas, constraints on the types are not validated.

This example is a simple type with email pattern constraint that we want to reuse:

Email = Dry::Types.module::Strict::String.constrained(
  format: /\A[^\s@]+@([\w\-]+\.)+(\w+{2,})\z/i,
  max_size: 254
)

We create a validation schema using the constrained type:

Schema = Dry:::Validation.Form do
  configure { config.type_specs = true }

  required(:email, Email).filled
end

Using the type, I get format error as expected:

Email["bogus"]
# => Dry::Types::ConstraintError: "bogus" violates constraints (format?(/\A[^\s@]+@([\w\-]+\.)+(\w+{2,})\z/i, "bogus") AND max_size?(254, "bogus") failed)

However, validating the schema I get no errors:

Schema.call(email: "bogus")
# => #<Dry::Validation::Result output={:email=>"bogus"} errors={}>

Furthermore, email can be any value and it seems that the schema ignores the type altogether.

Am I missing something?

Thanks!

~Joel


#2

After more combing through more GitHub code and Issues, I came across this issue, which passes the custom type to filled instead of passing it as the second argument to required:

So the way to get validations to work was this:

Schema = Dry:::Validation.Form do
  # No longer necessary to use type_specs?
  # configure { config.type_specs = true }

  required(:email).filled(Email)
end

What’s the type_specs configuration for? Why did the original way not work?

Thanks…!

~Joel


#3

OK, now the issue is that the type passed to filled loses all meta data. Why is that stripped?

The reason I need meta is to flag some fields for mapping between schemas. Previously I got the types via schema.type_map, then switching to the solution that fixed the issue in this thread, I needed to use schema.input_processor.member_types instead.

Now, the solution to retrieve meta from the type is to combine the problematic solution with the working validation solution, and then I get the meta from schema.type_map again.

Schema = Dry:::Validation.Form do
  configure { config.type_specs = true }

  required(:email, Email).filled(Email)
end

However, this seems redundant.

Anyone know why the meta on my Email type gets lost with required(:email).filled(Email)?

Thanks.

~Joel