Last active
February 21, 2021 13:37
-
-
Save favila/8ce31de4b2cb04cf202687c6a8fa4c94 to your computer and use it in GitHub Desktop.
Datomic transaction functions to "reset" attributes: i.e. make them have a post-transaction value you specify without having to enumerate the retractions.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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