Clojure Geek

Writing about learning Clojure

Using Records in Prismatic Schema

Previously I wrote about prismatic schema and records. Here I’m combining the two.

Add to project.clj

1
[prismatic/schema "1.0.5"]

Require in your file

1
[schema.core :as s]

Experimenting In the repl:

1
2
3
4
dev> (s/defrecord Recipe [name :- String  source :- String  url :- String  servings :- s/Int])

dev> (s/explain Recipe)
(record dev.Recipe {:name Str, :source Str, :url Str, :servings Int})

Using the function defrecord from schema, I created a record like in my last post on records. I added an additional field :serving to make it more interesting. Explain takes a record and does just that, explains it.

Validating a record is easy:

1
2
3
4
5
dev> (def tacos (->Recipe "Tacos" "Bob" "www.tacos.com" 4))
#'dev/tacos

dev> (s/validate Recipe tacos)
#dev.Recipe{:name "Tacos", :source "Bob", :url "www.tacos.com", :servings 4}

Doing an invalid record:

1
2
3
4
5
dev> (def pie (map->Recipe {:name "apple pie"}))
#'dev/pie

dev> (s/validate Recipe pie)
ExceptionInfo Value does not match schema: {:source (not (instance? java.lang.String nil)), :url (not (instance? java.lang.String nil)), :servings  (not (integer? nil))}  schema.core/validator/fn--11079 (core.clj:151)

I created the instance of the Pie recipe with just a name. With a regular record, it would have worked fine. But prismatic schema has these as required fields.

Also in addition to validate there is check, which returns nil if everything is good, or errors if not.

1
2
3
4
5
dev> (s/check Recipe (->Recipe "Choc Milk" "Charlie" "www.milk.com" 1))
nil

dev> (s/check Recipe (map->Recipe {:name "Apple Pie"}))
{:source (not (instance? java.lang.String nil)), :url (not (instance? java.lang.String

There is more things to learn with Prismatic Schema, but I am farther along now. :)

Comments