Skip to content

Instantly share code, notes, and snippets.

@dustingetz
Created September 19, 2019 00:58
Show Gist options
  • Select an option

  • Save dustingetz/7ca191dc69fc2e24ac1713e8a6ad2289 to your computer and use it in GitHub Desktop.

Select an option

Save dustingetz/7ca191dc69fc2e24ac1713e8a6ad2289 to your computer and use it in GitHub Desktop.
via Francis Avila
(def tx-fns
[{:db/ident :db.fn/reset-attribute-values
:db/doc "Transaction function which accepts an entity identifier, attribute identifier
and set of values and expands to any additions and retractions necessary to
make the final post-transaction value of the attribute match the provided
values. Attribute values must be scalars.
If multiple values are provided on a cardinality-one attribute you will get a
datom conflict exception at transaction time."
:db/fn (d/function
'{:lang "clojure"
:params [db lookup-ref attr values]
:code (let [e (d/entid db lookup-ref)
a (d/entid db attr)
old-values (into [] (map :v)
(d/datoms db :eavt e a))
new-values (into #{} values)]
(as-> (transient []) cmds
(reduce
(fn [cmds ov]
(if-not (contains? new-values ov)
(conj! cmds [:db/retract e a ov])
cmds))
cmds old-values)
(reduce
(fn [cmds nv] (conj! cmds [:db/add e a nv]))
cmds new-values)
(persistent! cmds)))})}
{:db/ident :db.fn/reset-attributes
:db/doc "Transaction function which accepts an entity identifier and a map of
attributes and values and expands to any additions and retractions necessary
to make the final post-transaction value of those attributes of the entity
match the value provided by the map. Attribute values must be scalars or sets
of scalars. The special value nil will retract all values of the attribute.
Attributes not mentioned by the map will not be altered. "
:db/fn (d/function
'{:lang "clojure"
:params [db lookup-ref attr-val-map]
:code (let [e (d/entid db lookup-ref)]
(into []
(keep
(fn [[attr xs]]
(if (= (:cardinality (d/attribute db attr))
:db.cardinality/many)
[:db.fn/reset-attribute-values e attr xs]
(if (nil? xs)
(when-some [oldv (-> (d/datoms db :eavt e
attr) first :v)]
[:db/retract e attr oldv])
[:db/add e attr xs]))))
attr-val-map))})}])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment