om

Please ask the channel first, not @dnolen directly!
carter.andrewj 2017-06-22T11:03:29.678768Z

Hi guys - running into a problem that I'm sure must be easy to solve: I need to mutate (specifically, to entirely replace) a normalized part of the db, but not sure how to go about it. Have tried (swap! state assoc-in [:field-1 :field-2] vector-of-maps) and (swap! state assoc :normalized/by-id map-of-stuff) but neither work. Have previously used the latter to successfully mutate fields within the normalized data, but I'm guessing I can't do that here (as it hasn't worked)? Have also experimented with tree->db, also with no joy. Any pointers?

2017-06-22T11:14:17.814406Z

I think tree->db is what you want, with a true third argument.

2017-06-22T11:14:41.819036Z

and (swap! state update merge result)

cjmurphy 2017-06-22T11:15:11.825447Z

@carter.andrewj: when you say it doesn't work, have you looked at the state in the REPL to see what it is like before and after the mutation?

carter.andrewj 2017-06-22T11:32:26.039404Z

Yeah - in each case, the result is: (swap! state assoc-in [:field-1 :field-2] vector-of-maps) = [{} {} {}] (essentially emptying the 3 entries that were there before (swap! state assoc :normalized/by-id map-of-stuff) = No change whatsoever tree->db (or my previous attempt thereof) = Uncaught Error: ... is not ISeqable

carter.andrewj 2017-06-22T11:32:36.041414Z

Will try now with the true arg

2017-06-22T11:33:42.054832Z

What's the full ISeqable error?

cjmurphy 2017-06-22T11:36:35.093750Z

(swap! state assoc-in [:normalized/by-id 20] map-of-stuff) - I would think that would be replacing the whole 'table record' that is held at the ident [:normalized/by-id 20].

carter.andrewj 2017-06-22T11:56:29.347414Z

@danielstockton Are you asking for the full stacktrace? The "..." is part of the error (presumably referring to the recursive part of the query in question).

2017-06-22T11:57:10.356315Z

Oh, I see.

carter.andrewj 2017-06-22T11:57:36.362164Z

No joy with tree->db. Which query should I be providing it? The root, the parent component, or the normalized component?

2017-06-22T11:58:22.372488Z

The parent component I think (one with the join).

carter.andrewj 2017-06-22T11:59:16.384528Z

Hmmm, that's what I'm currently trying

carter.andrewj 2017-06-22T11:59:37.389473Z

Let me throw a few print statements in - make sure I've not cocked something else up while changing things around

carter.andrewj 2017-06-22T12:10:54.549970Z

None of the inputs seem obviously wrong

carter.andrewj 2017-06-22T12:13:06.581101Z

If the query in question is [:foo :bar :normalized-thing {:more :fields}] then I should be passing to tree->db something like this: {:foo "x" :bar "y" :normalized-thing [:stuff :etc]} right?

carter.andrewj 2017-06-22T12:14:50.606605Z

Okay - I'm definitely doing something wrong with tree->db, the only change that happens to the input is that this gets added: {:om.next/tables #{}}

2017-06-22T12:18:16.657015Z

Do you mean [:foo :bar {:normalized-thing [:more :fields]}]?

2017-06-22T12:19:27.673865Z

And you should be passing tree->db {:normalized-thing [{...} {...} ...]}

carter.andrewj 2017-06-22T12:21:48.708267Z

Yes, sorry - that is the correct and current form of the query

carter.andrewj 2017-06-22T12:23:18.730355Z

I've fixed the above issue with no change happening in tree->db (forgot to revert a change I made during the earlier trial and error) and am now getting what looks like the expected result

carter.andrewj 2017-06-22T12:24:37.750463Z

However - the output has two main keys - :view-map and :view/by-id which are the non-normalized and normalized fields respectively

carter.andrewj 2017-06-22T12:25:18.760967Z

:view-map is now a vector of idents, as expected; and :view/by-id is the normalized input, also as expected

carter.andrewj 2017-06-22T12:26:20.776320Z

But - inspecting the app-state: :view-map is a child several layers from the root of the app-state, while :view/by-id sits at the root

carter.andrewj 2017-06-22T12:27:19.791970Z

So presumably I cannot just use (swap! state update merge result) with this output...?

carter.andrewj 2017-06-22T12:27:41.797235Z

(Well, I know I can't, because that's what it's still unsuccessfully set to try)

2017-06-22T12:28:09.804809Z

You'll have to merge it into app-state wherever your parser expects it to be.

2017-06-22T12:28:35.811528Z

I think :om.next/tables #{} should be at the root of the appstate though

carter.andrewj 2017-06-22T12:28:59.817804Z

But the output of tree-db is giving me things from different parts of the app state - one from the root, one from 2 levels deep

carter.andrewj 2017-06-22T12:29:31.826028Z

Do I need to merge the new :view-map into the app state, then pass that to tree->db with the root query...?

carter.andrewj 2017-06-22T12:29:35.827069Z

(Seems like overkill)

carter.andrewj 2017-06-22T12:30:02.834186Z

Or should I deconstruct the output of tree->db (and perform two merges)? Which seems brittle...

2017-06-22T12:32:02.866991Z

It sounds like you might want to rethink the queries to avoid duplicating the list in multiple places.

carter.andrewj 2017-06-22T12:32:23.872780Z

Duplicating the list?

carter.andrewj 2017-06-22T12:32:29.874443Z

Not sure I follow

carter.andrewj 2017-06-22T12:32:42.877650Z

The list only appears in one place in the raw app-state

carter.andrewj 2017-06-22T12:32:49.879700Z

The multiple places is done by om's normalization

2017-06-22T12:32:54.880855Z

I thought :view-map was the list of idents.

carter.andrewj 2017-06-22T12:33:02.883178Z

Only after normalization

2017-06-22T12:34:12.901639Z

does (merge-with merge app-state result) help merge both parts in a single merge?

carter.andrewj 2017-06-22T12:34:36.908016Z

Not really

carter.andrewj 2017-06-22T12:35:26.921717Z

The result has both keys at the same level, whereas they need to merge :view/by-id to the root and :view-map at [:analytics :dashboards]

carter.andrewj 2017-06-22T12:36:28.938178Z

I could break both out of the result and merge them independently - but that doesn't seem like it's how this is designed to work (so I'd worry I'm setting myself up for more pain further down the line...)

2017-06-22T12:37:13.950052Z

gotcha, sounds like the new data has a different shape from the old data. I think you'd probably have to pick apart the result and merge yourself. Otherwise, need to redesign the app-state.

carter.andrewj 2017-06-22T12:37:59.962682Z

Maybe my understanding of normalization is off? - as I understand it you start with {:foo {...} :bar {...} :stuff {:view-map [{...} {...} {...}]}}} and then get {:foo {...} :bar {...} :stuff {:view-map [ident ident ident]} :view/by-id {id1 {...} id2 {...} id3 {...}}} ...?

carter.andrewj 2017-06-22T12:38:38.973476Z

Should :view/by-id not end up in the root? (i.e. have I got something wrong with my idents, etc... elsewhere)

2017-06-22T12:39:02.979922Z

That's right, but if the list of idents is nested under [:analytics :dashboards] it means that your original data was deeply nested following this structure?

carter.andrewj 2017-06-22T12:39:17.983571Z

Yes, that is correct

2017-06-22T12:39:45.990673Z

But the novelty you want to merge doesn't have this nesting so I think it's on you to merge it back into app-state in the correct location.

carter.andrewj 2017-06-22T12:40:04.995687Z

Okay, that shouldn't be an issue

carter.andrewj 2017-06-22T12:40:30.002631Z

It doesn't feel right, but I get that a lot with om

carter.andrewj 2017-06-22T13:05:22.449867Z

Cheers, @danielstockton - that's working now

šŸ‘ 1
carter.andrewj 2017-06-22T13:06:14.466892Z

However, it doesn't appear to be treating the new entries in the normalized data as new - but rather as updates to the old entries

carter.andrewj 2017-06-22T13:06:51.479119Z

i.e. If there are 2 entries in the original data and 4 in the new, componentWillMount only fires for 3 and 4

carter.andrewj 2017-06-22T13:06:59.481725Z

Is this the expected behaviour?

2017-06-22T13:07:33.492858Z

The other components (existing idents) are probably already mounted so they'll fire componentWillUpdate instead?

carter.andrewj 2017-06-22T13:07:59.501248Z

Except the idents are changing

carter.andrewj 2017-06-22T13:08:35.512938Z

1 and 2 have completely different data (with the same shape) after the mutate

carter.andrewj 2017-06-22T13:08:46.516815Z

And they re-render with the new data

carter.andrewj 2017-06-22T13:09:33.531989Z

But they don't fire WillMount (which creates a problem, as that's where they set up a lot of initial conditions that then describes and triggers data to be pulled from a remote)

carter.andrewj 2017-06-22T13:10:05.542178Z

I could get round this via WillUpdate, but I suspect it's a symptom of me having done something wrong elsewhere

2017-06-22T13:12:02.580567Z

Can't say I've come across this.

2017-06-22T13:13:26.608610Z

Where is the new data coming from and how are you merging it in? Also, is the parent component being re-read?

carter.andrewj 2017-06-22T13:15:41.655540Z

The parent component is being re-read. If new-data = normalized data from above, that's built in the mutate from a config stored elsewhere in the app state.

carter.andrewj 2017-06-22T13:16:02.662621Z

(If you mean the data from the remote, that's coming down from an external postgresDB)

carter.andrewj 2017-06-22T13:17:15.687407Z

No worries for now - I need to go and grab some lunch anyway

carter.andrewj 2017-06-22T13:17:20.689428Z

Thanks for taking the time

2017-06-22T13:18:43.718743Z

No worries.

claudiu 2017-06-22T14:03:29.759982Z

Can anyone help me out with what Iā€™m doing wrong when checking in clj for om next component protocol ? Satisfies? always returns false (on cljs implements? works) ex: (satisfies? om/IQuery Item)

2017-06-22T14:06:02.823174Z

(extends? om/IQuery Item) @claudiu ?

2017-06-22T14:12:40.989586Z

satisfies? expects an instance, not a class.

2017-06-22T14:14:28.034697Z

There is also an (om/iquery? Item) function for this in om core.

claudiu 2017-06-22T14:16:22.083970Z

@danielstockton thank you. Will try it out.