03: queries

Queries tell Specmonstah what ents should exist in the ent db.

Section 3's source file begins:

(ns reifyhealth.specmonstah-tutorial.03
  (:require [reifyhealth.specmonstah.core :as sm]
            [loom.io :as lio]))

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

(defn ex-01
  []
  (sm/add-ents {:schema schema} {:post [[2]]}))

Queries are used to specify what ents should get generated. The term query might throw you off because usually it's used to refer to the language for retrieving records from a database. In Specmonstah, I think of queries as allowing you to express, generate the minimal ent-db necessary for me to retrieve the ents I've specified.

In ex-01, the query passed to sm/add-ents is {:post [[2]]}. This is like saying, I want two :posts. Create an ent-db with the minimum ents needed so that I can retrieve them. Because :post ents must refer to a :user, Specmonstah generates the :user ent :u0. Specmonstah only generates one :user, not two, because that's the minimum needed to satisfy the query.

Queries are maps, where each key is the name of an ent type, and each value is a vector of query terms. In the query {:post [[2]]}, :post is an ent type and [2] is a query term.

Each query term is a vector where the first element is either a number or an ent name. When you provide a number, as in [2], you're instructing SM to generate that many ents of the given ent type, and to name them according to its default naming system. As we saw in the last section, SM names ents by appending an index to the ent type's :prefix. The :prefix for :post is :p, so the :post ents are named :p0 and :p1. Figuring out what to name your test data is one of the tedious aspects of testing that SM handles for you.

On the other hand, if you do want to name an ent, you can provide a keyword as the first element in the query term, as in ex-02:

(defn ex-02
  []
  (sm/add-ents {:schema schema} {:post [[:my-post]
                                        [:blorp-post]]}))

(sm/view (ex-02))

Here, you're naming your :post ents :my-post and, in a fit of near whimsy, :blorp-post.

You can add as many query terms to an ent type as you want, mixing numbers and ent names as you please:

(defn ex-03
  []
  (sm/add-ents {:schema schema} {:post [[1]
                                        [:work]
                                        [1]
                                        [:cones-of-dunshire-club]]}))

Query terms take a second argument, an options map map, which is used to further tune the creation of the ent. The next section will show you how to use the options map to generate unique references.

Last updated