Coercion with the schema

Very often, we want to validate our data against some schema.compojure-api allows us to provide custom schema with constraints for our data.

For our cards entities, we can add the following constraints:

Create a util.clj file, where we'll include convenience functions:

(ns restful.util
(:require [clojure.string :as str]))

(def non-blank? (complement str/blank?))

(defn max-length? [length text]
(<= (count text) length))

(defn non-blank-with-max-length? [length text]
(and (non-blank? text) (max-length? length text)))

(defn min-length? [length text]
(>= (count text) length))

(defn length-in-range? [min-length max-length text]
(and (min-length? min-length text) (max-length? max-length text)))

We'll use these functions to define the schema for CardReqest, in cards.clj:

(ns restful.cards
(:require [compojure.api.sweet :refer [GET POST PUT DELETE]]
[restful.models.card :refer [Card]]
[restful.util :as str]
[ring.util.http-response :refer [ok not-found created]]
[schema.core :as s]
[toucan.db :as db]))

(defn valid-name? [name]
(str/non-blank-with-max-length? 50 name))

(defn valid-description? [description]
(str/length-in-range? 5 100 description))

(s/defschema CardRequestSchema
{:name (s/constrained s/Str valid-name?)
:description (s/constrained s/Str valid-description?)})

We've defined the schema for CardRequest, which should contain a valid :name and :description.