Skip to content

Instantly share code, notes, and snippets.

@nxtk
Forked from dustingetz/hyperfiddle-metamodel.md
Created October 10, 2019 01:52
Show Gist options
  • Save nxtk/8e960e0069058b679231296f9c4534c7 to your computer and use it in GitHub Desktop.
Save nxtk/8e960e0069058b679231296f9c4534c7 to your computer and use it in GitHub Desktop.
; This is the next iteration of the CRUD metamodel that powers Hyperfiddle
; Just a design sketch, the current metamodel in prod is different
; CRUD definition
{identity ; Pass through URL params to query
[{:dustingetz/event-registration ; virtual attribute identifying a query
[:db/id
(:dustingetz/email {:hf/a :dustingetz/registrant-edit}) ; hyperlink to detail form
:dustingetz/name
{:dustingetz/gender
[:db/ident]}
{:dustingetz/shirt-size
[:db/ident]}]}]
nil ; no query params
[{:dustingetz/genders ; picklist for genders
[:db/ident]}]
((hf/new) {:hf/tx :dustingetz/register}) ; generate a Datomic tempid and wire up a transaction
[:db/id
:dustingetz/email
:dustingetz/name
{:dustingetz/gender
[:db/ident
{:dustingetz/shirt-sizes ; shirt-size options depend on gender
[:db/ident]}]}
{:dustingetz/shirt-size
[:db/ident]}]}
; Queries
{:dustingetz/genders
[:find (pull ?e [:db/ident])
:where
[?e :db/ident ?i]
[(namespace ?i) ?ns]
[(ground "dustingetz.gender") ?ns]]
:dustingetz/shirt-sizes
[:in $ ?gender
:find (pull ?e [:db/ident])
:where
[?e :db/ident ?i]
[?e :dustingetz.reg/gender ?gender]
[(namespace ?i) ?ns]
[(ground "dustingetz.shirt-size") ?ns]]
:dustingetz/another-query ; just an example of how server code eval might work
(->> (d/q '[:in $ ?e
:find ?a ?v ?tx ?x
:where
[?e ?a ?v ?tx ?x]]
(d/history *$*)
%)
(map #(assoc % 0 (:db/ident (d/entity db (get % 0)))))
(group-by #(nth % 2))
(map-values #(sort-by first %))
(sort-by first))}
; Validation
(s/def :dustingetz/register (s/keys :req [:dustingetz/email
:dustingetz/name]
:opt [:dustingetz/gender
:dustingetz/shirt-size]))
; View progressive enhancement
(defmethod hyperfiddle.api/render #{:dustingetz/gender} ; custom renderer for ::gender
[ctx props]
[hfui/select ctx ; present as picklist
{:options :dustingetz/genders ; Wire up picklist options to named query
:option-label :db/ident}]) ; picklist label
(defmethod hyperfiddle.api/render #{:dustingetz/shirt-size} ; custom renderer for ::shirt-size
[ctx props]
[hfui/select ctx ; second picklist
{:options :dustingetz/shirt-sizes
:option-label :db/ident}])
; Transactions
(defmethod hyperfiddle.api/tx :dustingetz/register [ctx [e a v] props]
[[:db/add v :dustingetz/registered-date (js/Date.)]])
; Schema
[{:db/ident :dustingetz/name,
:db/valueType :db.type/string,
:db/cardinality :db.cardinality/one,
:db/doc "Registrant's name"}
{:db/ident :dustingetz/email,
:db/valueType :db.type/string,
:db/cardinality :db.cardinality/one,
:db/unique :db.unique/identity,
:db/doc "Registrant's email"}
{:db/ident :dustingetz/gender,
:db/valueType :db.type/ref,
:db/cardinality :db.cardinality/one,
:db/doc "Registrant's gender (for shirt size)"}
{:db/ident :dustingetz/shirt-size,
:db/valueType :db.type/ref,
:db/cardinality :db.cardinality/one,
:db/doc "Selected tee-shirt size"}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment