dry-rb/dry-validation

Conditionally Required Fields

Aperta

#582 aperta il 24 ago 2019

 (9 commenti) (10 reazioni) (0 assegnatari)Ruby (196 fork)github user discovery
featurehelp wanted

Metriche repository

Star
 (1422 stelle)
Metriche merge PR
 (Nessuna PR mergiata in 30 g)

Descrizione

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.

Guida contributor