Skip to content

Instantly share code, notes, and snippets.

@humorless
Forked from bobby/datomic-helpers.clj
Created March 19, 2021 16:54
Show Gist options
  • Save humorless/ff34d7ae722b7135454d3bfeec675c09 to your computer and use it in GitHub Desktop.
Save humorless/ff34d7ae722b7135454d3bfeec675c09 to your computer and use it in GitHub Desktop.
Some Datomic helpers I sometimes use with ring or pedestal-service apps
(ns datomic-helpers
(:require [datomic.api :as d]))
;;; Expose Datomic vars here, for convenience
;;; Ring middleware
(defn wrap-datomic
"A Ring middleware that provides a request-consistent database connection and
value for the life of a request."
[handler uri]
(fn [request]
(let [conn (d/connect uri)]
(handler (assoc request
:conn conn
:db (d/db conn))))))
;;; Sample handler
(defn create-entity-tx
"Dummy helper fn."
[db tempid]
[[:db/add tempid :db/doc "Some useful work should be done here."]])
(defn create-entity
"Include :db-after in response map, so that middleware on the way
\"out\" have updated db value. Or you could include the entire tx
result."
[{:keys [conn db] :as request}]
(let [tempid (d/tempid :db.part/user)
result @(d/transact conn (create-entity-tx db tempid))]
{:status 201
:body "Done!"
:headers {}
:db-after (:db-after result)}))
;;; Rules-based predicates
(defn predicate-from-rules
"Returns a predicate fn that will return true when the predicate-rules (a subset of
the source-rules) are satisfied, and false otherwise."
[source-rules predicate-rules]
(fn [entity]
(when entity
(boolean
(ffirst
(q (concat '[:find ?e
:in $ $id %
:where [(= ?e $id)]]
predicate-rules)
(:db/id entity)
source-rules))))))
;;; Map => Transaction Helpers
;; The functionality that was previously here is now provided by
;; Datomic: i.e. nested maps in transactions.
;;; Query
;; For a better set of query helpers, please see https://github.com/Datomic/day-of-datomic/blob/master/src/datomic/samples/query.clj
;;; Enum => HTML <select> options
(def dropdown-schema
[{:db/id (tempid :db.part/db)
:db/ident :option/text
:db/valueType :db.type/string
:db/index true
:db/cardinality :db.cardinality/one
:db/doc "The user-facing text content of an option tag"
:db.install/_attribute :db.part/db}
{:db/id (tempid :db.part/db)
:db/ident :option/value
:db/valueType :db.type/string
:db/index true
:db/cardinality :db.cardinality/one
:db/doc "The user-facing value attribute of an option tag"
:db.install/_attribute :db.part/db}
{:db/id (tempid :db.part/db)
:db/ident :option/attribute
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The attribute to which this option corresponds"
:db.install/_attribute :db.part/db}])
(defn option-value->ident
"Given an attribute and an option value, returns the correpsonding datomic entity ident."
[attribute value]
(ffirst
(q '[:find ?ident
:in $ ?attribute ?value
:where
[?e :option/value ?value]
[?e :option/attribute ?a]
[?e :db/ident ?ident]
[?a :db/ident ?attribute]]
attribute
value)))
(defn attribute->options
"Returns all the valid options for the given attribute."
[attribute]
(find-all
'[:find ?e
:in $ ?attr
:where
[?e :option/attribute ?a]
[?a :db/ident ?attr]]
attribute))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment