How to compose params?

Hi everyone

I have a params class

module MyApp
  module Actions
    module Document
      module Params
        class Create < Hanami::Action::Params
          params do
            required(:title).filled(:string)
            required(:template).filled(:string)
  
            optional(:type).value(:string)
            optional(:number).value(:string)
          end
        end
      end
    end
  end
end

I use this schema in my action

params Params::Create

I would like to compose in my another action

params Params::Create
  optional(:documents).value(:array, min_size?: 1).each do
     schema(Params::Create)
   end
end

I have tried several attempts but without success

Also, as I see, It is impossible to pass array without root and validate it

e.g.

using:

[
  {}, {}
]

instead of

{
  documents: []
}

Use Dry::Schema directly instead of Hanami::Action::Params. This will allow the usual kind of composition.

Hanami::Action::Params is a legacy of Hanami 1.0, and the current plan is to deprecate it now that both Dry::Schema and Dry::Validation::Contract are supported directly.

I don’t believe top-level arrays have ever worked with Dry::Schema, you will need to nest them under a key.

Thanks for your response!

@alassek
I only find this way using directly Dry::Schema::Params

module MyApp
  module Actions
    module Users
      module Params
        Create = Dry::Schema.Params do
          required(:name).filled(:string)
          required(:email).filled(:string)
        end
      end
    end
  end
end

but it seems to me that this syntax is too cumbersome

def handle(request, response)
  params_result = Params::Create.call(request.params)

  unless params_result.failure?
    halt 422, { errors: params_result.errors.to_h }.to_json
  end

May be short syntax exists

UPT
I have found out how to do this

module MyApp
  module Actions
    module Users
      module Contracts
        class Create < Dry::Validation::Contract
          params do 
            required(:name).filled(:string)
            required(:email).filled(:string
          end
        end
      end
    end
  end
end

and in controller:

contract Contracts::Create