I'm following Chapter 6 of the book Professional Clojure.
App state is currently defined as follows:
(defonce app-state
(reagent/atom
{:projects
{"aaa"
{:title "Build Whip"
:stories
{1 {:title "Design a data model for projects and stories"
:status "done"
:order 1}
2 {:title "Create a story title entry form"
:order 2}
3 {:title "Implement a way to finish stories"
:order 3}}}}}))
I need to use swap!
to add a new key value to represent a new story, keyed by an id with value of the given fields.
(defn add-story! [app-state project-id title status] ;
; Q. How to use swap! to add a key value pair into :stories?
(swap! app-state update [:projects project-id :stories] assoc <- INCORRECT CODE HERE
(unique) {:title title
:status status
:order (inc (max-order app-state project-id))}))
The unique function not shown here just generates any unique uuid. The max-order function gets, well, the max order. I had to modify it as the book chapter proceeds inconsistently with the actual final code supplied. Here's my version of max-order:
(defn max-order [app-state project-id]
(apply max 0 (map :order (vals (get-in @app-state [:projects project-id :stories])))))
Question: How can I use swap!
to add a new key value into :stories
?
I had a go at it but it beat me for now.
I do get the feeling this nested map is not the best representation - in the final code supplied as a download the author has changed to a more relational-type model with projects and stories both as top level entities, with stories containing a project_id, but would be nice to solve this first use of swap!
before moving on to that.
I think you can just use assoc-in
in this case which is a bit simpler than update-in
and better describes what you're trying to achieve:
(def app-state
(atom
{:projects
{"aaa"
{:title "Build Whip"
:stories {1 {:title "Design a data model for projects and stories"
:status "done"
:order 1}
2 {:title "Create a story title entry form"
:order 2}
3 {:title "Implement a way to finish stories"
:order 3}}}}}))
(defn unique [] (rand-int 1000000000))
(let [unique-key (unique)]
(swap! app-state
assoc-in
[:projects "aaa" :stories unique-key]
{:title (str "Agent " unique-key)
:status "foxy"
:order "some-order-stuff"}))
@app-state
;; => {:projects
;; {"aaa"
;; {:title "Build Whip",
;; :stories
;; {1 {:title "Design a data model for projects and stories", :status "done", :order 1},
;; 2 {:title "Create a story title entry form", :order 2},
;; 3 {:title "Implement a way to finish stories", :order 3},
;; 295226401 {:title "Agent 295226401", :status "foxy", :order "some-order-stuff"}}}}}