Fork me on GitHub
#om
<
2016-06-15
>
acron16:06:33

What's the canonical way of deleting an entry in normalized data?

{:list/one [[:person/by-name "John"] [:person/by-name "Mary"] [:person/by-name "Bob"]],
 :list/two [[:person/by-name "Mary"] [:person/by-name "Gwen"] [:person/by-name "Jeff"]],
 :person/by-name
 {"John" {:name "John", :points 0},
  "Mary" {:name "Mary", :points 1, :age 27},
  "Bob" {:name "Bob", :points 0},
  "Gwen" {:name "Gwen", :points 0},
  "Jeff" {:name "Jeff", :points 0}}}
This is taken from the Wiki example. In a mutate function operating on the data, how would I remove a person? An an example, just removing it from the :persons/by-name key leaves it in the :list/one/`:list/two` keys so the UI still renders it.

acron16:06:20

It feels like the mutate function shouldn't have to remove it everywhere it's featured...that's the point of normalisation, right?

cjmurphy16:06:33

@acron: I think you just have to remove it from :persons/by-name and every refs list that points to that table, just as you say. Seems sensible to create functions to do this for you. Here's the generic delete I use. It only removes from one referencing place, so needs improving for your case.

acron16:06:56

thanks @cjmurphy. As a relevant question, is normalisation mandatory? Seems like I'm spending a lot of time fighting it

cjmurphy16:06:31

Not mandatory. I think in terms of yes spend a lot of time with it, but activities are just different to other types of programming. It is like mutations are the only serious programming that needs to be done.

cjmurphy16:06:41

Not mandatory but anything else would be for a very special use case I think.

acron16:06:15

@cjmurphy: Ok, I'll stick with it for now...your fn has helped a lot so thanks

acron16:06:31

The other trick, of course, is persuading the UI element to re-render once removing the Person

cjmurphy16:06:05

For removing a person from many then that's not too tricky - the transact! has to be where this is the parent component. Follow on reads a bit more difficult for me: I often use idents as follow on reads, just to specifically re-render a particular component. I ought to use keywords - in fact ought to replace all those uses with keywords.

cjmurphy16:06:34

Sometimes having two components sharing the same ident can be helpful too.

acron16:06:54

@cjmurphy: That's an interesting nuance I wasn't aware of - transact!s need to always be on the parent UI?

cjmurphy16:06:31

When deleting they need to be, because delete is an operation of the whole list.

cjmurphy16:06:53

Also add is an operation of the whole list.

acron16:06:13

Okay...so even using :value in a mutate isn't enough to persuade a parent to re-render?

cjmurphy16:06:56

:value doesn't mean anything - only the :action does.

acron16:06:39

Ok, good to know

cjmurphy17:06:31

Yep - that's asked all the time here - 'just for documentation' is the answer for the purpose being :value

acron17:06:22

Makes it hard to feature a 'delete me' element on a UI element then

cjmurphy17:06:36

Not so hard because you have computed to pass whatever you need down to the child.

cjmurphy17:06:27

Either a function or the parent itself can be passed in computed.

acron17:06:19

Yeah, that's a good point.

petterik19:06:15

@anmonteiro: re: path navigation: Sorry for the late answer. I'm using a bidi+pushy approach and creating mutations depending on the url structure. That part is alright. It seems like path navigation is a separate concern than routing (if done right). My biggest problem with routing has been sending the correct query to the remote(s). When I've gone with either subquery or set-query! solutions, the full-query has depended on props, and when gather-sends is called after a transact! with a route change mutation, the query hasn't been up-to-date. So I've had to transact! route changes, then - possibly multiple - set-query!, then a last transact! to gather-sends and using different hacks to prevent multiple requests. I can now imagine a solution with unions that doesn't have problems with getting the remote query correct. I'll try to re-write our routing with unions and then probably transition to your lib. I'll let you know how it goes! Thanks ✌️