Thanks for that, Mike. Like I've written earlier in this thread, I've been 
trying a few approaches and have been wondering what others have come up with. 
(I don't need to reinvent the wheel.)

I hadn't quite gotten as far as you've described, though I was definitely on 
that path with one approach. Another I've tinkered with is using clojure.walk, 
but I dislike that it touches every node. Expensive on a large data set. 
Zippers don't make me happy either.

Definitely agree with keeping data as flat as possible, but even so you can end 
up with a decent tree shape, which the data structures I'll be consuming and 
generating actually have.

In my app, a Product is a Component (not a React/Reagent/Om component) that has 
many Components. Each Component can have many Components or many Substances. 
Even though the components are stored flat, they form a logical tree of 
n-levels of Components. Components and Substances can have other lists as well.

So, you can see that my needs to traverse into a rich data structure are 
immediate, even with flattened storage of the Components in a single list on 
the root Product.

Interestingly, last Summer I started on this with Reagent and later Om using 
the unflattened data (why?--it was flat in the db!). It got turned into an app 
for different data that was not recursive in any way, but I'd still solved that 
problem. I turned to Om then b/c it has cursors and they solved this problem so 
well that I felt it was worth the other pains involved in using Om, so I gave 
up on Reagent. In a nutshell: Reagent made developing React-style components 
really simple and easy, but dealing with a rich app-data atom was such a PITA, 
that I switched to Om whose cursors made that easy while making component 
development much more cumbersome. Since seeing and playing with Re-Frame, I've 
decided to do this next project with re-frame. 

Anyway, thanks again for the info, as it definitely helps me along.

Jamie


On Mar 25, 2015, at 9:46 PM, Mike Thompson <[email protected]> wrote:

> On Thursday, March 26, 2015 at 2:08:23 AM UTC+11, Jamie Orchard-Hays wrote:
>> In Om, I didn't have to think about how to find the data in app-db to update 
>> as Om has cursors. In the cursorless world of re-frame, I am wondering what 
>> are favorite strategies for updating data deep inside a decently rich app-db 
>> tree.
>> 
>> ie, say I want to update a field that is in a map that is in a list in 
>> app-db. I want to update the :name value in one of the maps in :some-list:
>> 
>> (def app-db (atom
>>  {:some-list
>>    [{:id "asdfadfa" :name "Foo Bar" ...}
>>     {:id "gfdsalkjc" :name "Boo Baz" ...}
>>     ....]}))
>> 
>> This isn't so difficult to approach, but what about a field in a map in a 
>> list in a map in a list... You get the idea.
>> 
> 
> 
> Tim Peters guides us in this area by recommending:  "Flat is better than 
> nested". 
> https://www.python.org/dev/peps/pep-0020/
> 
> But that isn't always possible, I know, so to answer your question instead of 
> providing gratuitous quotations ... 
> 
> As much as possible, I try to conceptualise "app-db" to be a database. That's 
> the reason for that "db" in the name. 
> 
> And, if you wanted to "update" a database, you need:
>   - the unique key of the thing to be updated
>   - the name of the table (collection).
> 
> Generally "path middleware" nicely handles the "name of the table" part of 
> this pair.  It gets your handler to the "root" of the data structure (table? 
> collection?). 
> 
> In the situation you are describing, the "unique key" bit is some sort of 
> "path" into a data structure. There are layers of vectors and maps to 
> traverse, even if middleware gets you to the base of this data structure you 
> want to update. 
> 
> In such a case, you'll have to "build the unique key" as you descend. A 
> read-only cursor-like process. 
> 
> So, let's imagine you represent your path as a vector (of keys or indexes), 
> then in each level you would pass down this path vector, conj-ed with a new 
> part of the id, incrementally building the unique key as you descend, and 
> passing it down.
> 
> Then, at the leaves, when you "dispatch", you can include the path vector in 
> the event payload.  The handler then has the information it needs to perform 
> the update. 
> 
> This deep-tree situation is not a common usecase for me, but if you ran into 
> this situation a lot, then I'd think about adapting the reagent cursors for 
> the job.
> 
> In summary:  when you dispatch, pass through the "unique key" (path), of the 
> thing you want updated.   Your handler may additionally have "path 
> middleware" on it, which resolves the “name of the table” part of any update. 
>  So you get the job done via that combination. 
> 
> A super simple version of this, can be seen here:
> https://github.com/Day8/re-frame/blob/46b8848f3bab432832a4517f0cccf36cb4197f65/examples/todomvc/src/todomvc/handlers.cljs#L54-L58
> 
> "todo-ware" contains path middleware which gets the handler directly to the 
> "todos table" (see the parameter "todos"), and the "id" in the event is the 
> unique key required for the update. In your case, you'd just have a more 
> complicated "id" (it's a vector created in a read-only cursor-like fashion).  
> 
> I worry that I've simply told you what you already know here.
> 
> 
> --
> Mike
> 
> 
> -- 
> Note that posts from new members are moderated - please be patient with your 
> first post.
> --- 
> You received this message because you are subscribed to the Google Groups 
> "ClojureScript" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/clojurescript.

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to