Is this possible to do with dry-validation?


#1

Hi there, I’m trying to use Dry::Validation to validate a JSON-API service and I’m running into a roadblock with the data member.

According to the spec, data must either be a single resource object, or an array of resource objects.

I have a Resource validation that looks like

Resource = Dry::Validation.JSON do
  configure { config.type_specs = true }

  required(:type, "strict.string").filled
  required(:id, "coercible.integer").filled
  optional(:attributes, Types::Hash)
  optional(:relationships, Types::Hash)
  optional(:links, Types::Links)
  optional(:meta, Types::Hash)
end

And now I’m trying to embed this into a larger Document validation but I have no idea how to express an object or array validation.

Document = Dry::Validation.JSON do
  configure { config.type_specs = true }

  required(:data).each { schema Resource }

  optional(:included).each { schema Resource }

  optional(:links, Types::Links)
  optional(:meta, Types::Hash)

  optional(:jsonapi, Types::Hash)
end

I’ve looked at a lot of example validations, and I have never seen one like I need. Is this even possible?


#2

Something like this:

required(:data) { each(schema(Resource)) | schema(Resource) }

#3

No luck :slightly_frowning_face:

Doing what you suggest gives me:

Failure/Error: each(schema(Resource)) | schema(Resource)

ArgumentError:
  is_a? predicate arity is invalid

I suspect that each doesn’t support passing an argument like that… so I tried:

required(:data) do
  schema(Resource) | each { schema(Resource) }
end

This compiles, however now it fails no matter what I pass in:

subject.(data: { id: "123", type: "foo" })
=> Failure({:data=>["data is missing"]})

subject.(data: [{ id: "123", type: "foo" }])
=> Failure({:data=>["data is missing"]})