From 3fcd6cfd73c9c076d5f1d4010b515fe2185cb412 Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Fri, 31 Jan 2025 14:31:54 +0200 Subject: [PATCH] doc: document nested parameter definitions originally implemented in #626 for #422 --- doc/basics/route_data.md | 2 ++ doc/ring/coercion.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/doc/basics/route_data.md b/doc/basics/route_data.md index 701c9ec0..709db3d6 100644 --- a/doc/basics/route_data.md +++ b/doc/basics/route_data.md @@ -85,6 +85,8 @@ Resolved route tree: ; :roles #{:db-admin}}]] ``` +See also [nested parameter definitions for coercions](../ring/coercion.md#nested-parameter-definitions) + ## Route Data Fragments Just like [fragments in React.js](https://reactjs.org/docs/fragments.html), we can create routing tree fragments by using empty path `""`. This allows us to add route data without accumulating to path. diff --git a/doc/ring/coercion.md b/doc/ring/coercion.md index 1f4d737c..342f1020 100644 --- a/doc/ring/coercion.md +++ b/doc/ring/coercion.md @@ -63,6 +63,36 @@ Handlers can access the coerced parameters via the `:parameters` key in the requ :body {:total total}}))}) ``` + +### Nested parameter definitions + +Parameters are accumulated recursively along the route tree, just like +other [route data](../basics/route_data.md). There is special case +handling for merging eg. malli `:map` schemas. + +```clj +(def router + (reitit.ring/router + ["/api" {:get {:parameters {:query [:map [:api-key :string]]}}} + ["/project/:project-id" {:get {:parameters {:path [:map [:project-id :int]]}}} + ["/task/:task-id" {:get {:parameters {:path [:map [:task-id :int]] + :query [:map [:details :boolean]]} + :handler (fn [req] (prn req))}}]]] + {:data {:coercion reitit.coercion.malli/coercion}})) +``` + +```clj +(-> (r/match-by-path router "/api/project/1/task/2") :result :get :data :parameters) +; {:query [:map +; {:closed true} +; [:api-key :string] +; [:details :boolean]], +; :path [:map +; {:closed true} +; [:project-id :int] +; [:task-id :int]]} +``` + ## Coercion Middleware Defining a coercion for a route data doesn't do anything, as it's just data. We have to attach some code to apply the actual coercion. We can use the middleware from `reitit.ring.coercion`: