Top level logic validation

Hey Stas. :wave: This question is tangentially similar to what was asked earlier here but I think your question can probably be solved through pattern matching in this situation. Here’s a little script you can tinker with that should demonstrate a potential solution for you:

#! /usr/bin/env ruby
# frozen_string_literal: true

# Save as `snippet`, then `chmod 755 snippet`, and run as `./snippet`.

require "bundler/inline"

gemfile true do
  source "https://rubygems.org"

  gem "amazing_print"
  gem "debug"
  gem "dry-schema"
end

module Schemas
  User = Dry::Schema.Params { required(:name).filled :string }
  Admin = Dry::Schema.Params { required(:email).filled :string }
  Unknown = proc { "Unknown parameters." }
end

class Validator
  SCHEMAS = {user: Schemas::User, admin: Schemas::Admin, unknown: Schemas::Unknown}.freeze

  def initialize schemas: SCHEMAS
    @schemas = schemas
  end

  def call(parameters) = find_schema(parameters).call parameters

  private

  attr_reader :schemas

  def find_schema parameters
    case parameters
      in name:, **remainder unless remainder.key? :email then schemas.fetch :user
      in email:, **remainder unless remainder.key? :name then schemas.fetch :admin
      else schemas.fetch :unknown
    end
  end
end

validator = Validator.new

ap validator.call({name: "Jane Doe"})
ap validator.call({email: "Jill Smith"})
ap validator.call({name: "Invalid", email: "admin@example.com"})

When running the above you’ll see the following output:

#<Dry::Schema::Result{:name=>"Jane Doe"} errors={} path=[]>
#<Dry::Schema::Result{:email=>"Jill Smith"} errors={} path=[]>
"Unknown parameters."

You’ll notice that the validator handles a user, admin, and unknown data (simple use case but you can make it as sophisticated as needed). Basically, I’m using pattern matching to delegate to the appropriate schema to determine which schema to validate against. This assumes you have distinguishing keys withing your parameters to route to the appropriate schema, though.

Anyway, might be of interest as one solution.