How to add a custom validation rule to a dry-type?

I want to define a Type for a local file path. I want to validate that the local path exists and points to a file. I also want to add this validation rule to the Type itself, so I don’t have to add duplicate rule()s to my various Dry::Validation::Contract classes.

That’s an interesting thought. I don’t believe this is possible currently with just a type, it would probably need to exist as a dry-logic predicate first maybe.

I think the easiest, most reusable way to achieve this today would be dry-validation macros

Types = Dry.Types(default: :strict)

module Types
  Pathname = Constructor(::Pathname)
end

Dry::Validation.register_macro(:file_exists) do
  unless Types::Pathname[value].exist?
    key.failure("file not found")
  end
rescue Dry::Types::CoercionError
  key.failure("not a valid Pathname")
end

class Contract < Dry::Validation::Contract
  schema do
    required(:filename).value(Types::Pathname)
  end

  rule(:filename).validate(:file_exists)
end
1 Like