Using Prismatic/schema for form validation with Liberator

1.7k Views Asked by At

Is Prismatic/schema a good fit for form validation? I have never designed a form validation lib before, but I imagine it outputting something like this instead of throwing exceptions on s/validate:

{::errors {:name [{:missing "Required field."}
                  {:length "Must be at least 3 characters."}]
           :email [{:email "Must be a valid email address"}]}}

I'm hoping someone has used it with Compojure and Liberator, but I can't find anything online.

3

There are 3 best solutions below

1
On

Found some great helpers in Dante on GitHub, but the licence for use is not clear:

(ns dante.tools.schemas
  (:require [dante.tools.namespaces :refer [export]]
            [schema.core :as s]
            [schema.coerce :as coerce]
            [schema.utils :refer [validation-error-explain]])
  (:import [schema.utils NamedError ValidationError]))

(defn explain [errors]
  (cond
   (map? errors)
   (->> errors
        (map (fn [[k v]]
               [k (explain v)]))
        (into {}))

   (or (seq? errors)
       (coll? errors))
   (map explain errors)

   (instance? NamedError errors)
   [(.name errors)
    (explain (.error errors))]

   (instance? ValidationError errors)
   (str (validation-error-explain errors))

   :else
   (str errors)))

(defn- coercercions [schema]
  (or
   (coerce/+string-coercions+ schema)
   (coerce/set-matcher schema)))

(defn validate [schema value]
  ((coerce/coercer schema coercercions) value))
0
On

I have been using Schema for shared form validation (ClojureScript) and server side (Clojure) for some time and it has turned out very well.

I originally posted a suggestion for using Schema in this way on GitHub:

Link here

Let me know if you would like further examples.

0
On

From your description of the error map you want on validation failure, it looks like Validateur would fit. Quoting from their Getting Started page:

Validateur is a validation library inspired by Ruby's ActiveModel. Validateur is functional: validators are functions, validation sets are higher-order functions, validation results are returned as values.

Around this small core, Validateur can be extended with any custom validator you may need: it is as easy as defining a Clojure function that conforms to a straightforward contract.