07: spec gen customization and omission

You can override the values produces by ent-db-spec-gen in the query:

(ns reifyhealth.specmonstah-tutorial.07
  (:require [reifyhealth.specmonstah.core :as sm]
            [loom.io :as lio]
            [clojure.spec.alpha :as s]
            [reifyhealth.specmonstah.spec-gen :as sg]))

(s/def ::id (s/and pos-int? #(< % 100)))
(s/def ::not-empty-string (s/and string? not-empty #(< (count %) 10)))

(s/def ::username ::not-empty-string)
(s/def ::user (s/keys :req-un [::id ::username]))

(s/def ::name ::not-empty-string)
(s/def ::topic (s/keys :req-un [::id ::name ::owner-id]))

(s/def ::owner-id ::id)
(s/def ::topic-id ::id)
(s/def ::content ::not-empty-string)
(s/def ::post (s/keys :req-un [::id ::owner-id ::topic-id ::content]))

(def schema
  {:user  {:prefix :u
           :spec   ::user}
   :topic {:prefix    :t
           :spec      ::topic
           :relations {:owner-id [:user :id]}}
   :post  {:prefix    :p
           :spec      ::post
           :relations {:topic-id [:topic :id]}}})

(defn ex-01
  []
  (sg/ent-db-spec-gen-attr {:schema schema}
                           {:user [[1 {:spec-gen {:username "barb"}}]]
                            :post [[1 {:spec-gen {:content "so good to be barb"}}]]}))

(ex-01)
;; =>
{:p0 {:id 81, :owner-id 96, :topic-id 68, :content "so good to be barb"}
 :t0 {:id 68, :name "3l1IR8", :owner-id 3}
 :u0 {:id 3, :username "barb"}}

We're using the same specs and schema as in the last section. Things get interesting at line 34, where we have this query:

{:user [[1 {:spec-gen {:username "barb"}}]]
 :post [[1 {:spec-gen {:content "so good to be barb"}}]]}

In the refs section we saw that query terms could take an optional map. Here, the optional maps are {:spec-gen {:username "barb"}} and {:spec-gen {:content "so good to be barb"}} . When you include :spec-gen key, the associated map is merged into whatever value is generated by clojure.spec.

You can also specify that you don't want an ent to reference one of the ents defined in its schema. For example, if a :todo-list's :owner-id is optional and you don't want it to be present, you could do this:

(defn ex-02
  []
  (sg/ent-db-spec-gen-attr {:schema schema}
                           {:topic [[1 {:refs {:owner-id ::sm/omit}}]]}))
(ex-02)
;; =>
{:t0 {:id 12, :name "418y13ST"}}

::sm/omit prevents the referenced ent from even being created in the ent db. It's as if the :owner-id relation didn't exist in the schema. spec generation respects this and omits :owner-id from the map it generates. If you want the key :owner-id to be present with the value nil, you'd have to specify that like this:

(defn ex-03
  []
  (sg/ent-db-spec-gen-attr {:schema schema}
                           {:topic [[1 {:refs     {:owner-id ::sm/omit}
                                        :spec-gen {:owner-id nil}}]]}))

(ex-03)
;; =>
{:t0 {:id 2, :name "pijm" :owner-id nil}}

Last updated