Skip to content

Instantly share code, notes, and snippets.

@raymcdermott
Last active December 7, 2015 21:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raymcdermott/57ade5ae671f83d2444e to your computer and use it in GitHub Desktop.
Save raymcdermott/57ade5ae671f83d2444e to your computer and use it in GitHub Desktop.
CRUD on component entities ... more support than comes out of the box with Datomic
(def component-crud
(d/function
'{:lang "clojure"
:params [db entity comp-key]
:code (if-let [db-entity (d/pull db '[*] (:db/id entity))]
(let [db-comps (comp-key db-entity)
user-comps (comp-key entity)
s1 (into #{} (map :db/id db-comps))
s2 (into #{} (map :db/id user-comps))
diffs (clojure.set/difference s1 s2)
retractions (into [] (map (fn [e] [:db.fn/retractEntity e]) diffs))
existing-comps (filter :db/id user-comps)
new-comps (remove :db/id user-comps)
datomicized-comps (map #(assoc % :db/id (d/tempid :db.part/user)) new-comps)
comp-entities (into [] (reduce into [existing-comps datomicized-comps]))
updated-entity (assoc entity comp-key comp-entities)]
(if (empty? retractions)
(vector updated-entity)
(conj retractions updated-entity))))}))
@raymcdermott
Copy link
Author

The incoming structure is assumed to be a map that represents an entity. Component entities are list of maps on a property so a simple album with tracks might look like this:

{:db/id 17592186045460,
  :xx/id #uuid"57575100-a6d6-48e8-97f1-cd187bd3d3f5",
  :xx/name "The XX",
  :xx/xx-tracks [{:track/name "XYZ", :track/length 360}]}

This would work out of the box with Datomic.

It is not currently possible to easily add more tracks or provide a list of new tracks that would automatically retract existing tracks (assuming that's a semantic you want!). The above code fixes that and a blog post with more details is forthcoming.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment