dry-rb/dry-validation

Conditionally Required Fields

Open

#582 opened on Aug 24, 2019

View on GitHub
 (9 comments) (10 reactions) (0 assignees)Ruby (193 forks)github user discovery
featurehelp wanted

Repository metrics

Stars
 (1,421 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

In many REST APIs it's often the case when creating resources, certain fields are required but when updating resources, all fields are optional and only the fields which are provided are updated.

Examples

For example, the following schema is good for validating user creation.

  params do
    required(:name).filled(str?)
    required(:phone_number).filled(:str?)
    optional(:metadata).maybe(:hash?)
    required(:additional_details).filled(:hash?).schema do
      required(:name_km).filled(:str?)
      required(:date_of_birth).value(:date, :filled?)
    end
  end

But when updating a user, we need the following schema:

  params do
    optional(:name).filled(str?)
    optional(:phone_number).filled(:str?)
    optional(:metadata).maybe(:hash?)
    optional(:additional_details).filled(:hash?).schema do
      optional(:name_km).filled(:str?)
      optional(:date_of_birth).value(:date, :filled?)
    end
  end

We don't want to repeat the schema and the rules

My first thought of a possible solution would be something like:

  option :resource, optional: true

  params do
    conditionally_required(:name).filled(str?) { resource.present? }
    conditionally_required(:phone_number).filled(:str?) { resource.present? }
    conditionally_required(:metadata).maybe(:hash?) { resource.present? }
    conditionally_required(:additional_details).filled(:hash?) { resource.present? }.schema do
      conditionally_required(:name_km).filled(:str?)  { resource.present? }
      conditionally_required(:date_of_birth).value(:date, :filled?)  { resource.present? }
    end
  end

For a PATCH request, the resource could be injected as an external dependency, for a POST request the resource doesn't exist yet so it's not injected.

Contributor guide