om-next 2017-11-17

@daniel.dyba has joined the channel

I have some data that I’ve fetched from the server, but it’s not in the format that I want to store it in the global atom. How would I go about modifying the response and storing it in the correct location in the atom? I’ve been considering adding a :merge option to my reconciler configuration. At this point, I’m reading the source code to figure out how this works and I’m at a loss for what to put in :tempids.

sova-soars-the-sora 2017-11-17T17:19:53.000758Z

@daniel.dyba welcome! om next is really great. i recommend asking your question in the #om channel or even in the #clojurescript channel. I have code that figures out where things live in the clientside/js/browser atom and slides them on in. let me see if I can find an example for you my good man.

@sova thanks! do the #om and #clojurescript channels have more activity?

I figured I’d choose this channel because it’s om-next specific

sova-soars-the-sora 2017-11-17T17:22:43.000347Z

#om has more activity this #om-next channel is not really where discussions go down (david nolen creator of om and om.next and antonio [co-maintainer] spend their time in #om

ah, thanks for the tip! @sova

sova-soars-the-sora 2017-11-17T17:23:17.000414Z

So I had to ask for help writing a merge function for the local atom...

sova-soars-the-sora 2017-11-17T17:23:29.000218Z

@joshjones hooked me up with a great chunk of code 😃

sova-soars-the-sora 2017-11-17T17:24:00.000578Z

I'll paste you what I have, it has been catered to my specific situation

the last time I tried writing a custom merge function, I found myself in an infinite loop 😕

it kept re-rendering the components

sova-soars-the-sora 2017-11-17T17:25:16.000602Z

So you can click to expand that snippet.

sova-soars-the-sora 2017-11-17T17:25:52.000187Z

Hmm this is more for updating an existing (nested) set of atom values [some of my items have "ratings" and there's one "active blurb" that has its own ID.

@sova which one is the custom merge function? Neither seems to have the correct number of arguments

sova-soars-the-sora 2017-11-17T17:26:37.000140Z

Anyway, I don't want to confuse you, there are experts that can help in #om for sure, but you can see that this snippet uses merge. you may have to use merge-with sometimes as to not overwrite the existing atom with just 1 entry

sova-soars-the-sora 2017-11-17T17:27:41.000345Z

Okay well, tell me more about your data

sova-soars-the-sora 2017-11-17T17:28:45.000449Z

So you get some entries from the server, you want to insert them into the atom in the right place, yar?

sova-soars-the-sora 2017-11-17T17:29:16.000281Z

well this function actually uses assoc

sova-soars-the-sora 2017-11-17T17:29:30.000177Z

and a lot of my functions to add into the atom use assoc-in

Line 2355 pulls the custom merge function I specify when I create my reconciler and then my custom merge gets called on Line 2356

It requires that I return a map with :keys, :next, and :tempids. I know what to put in :keys and :next but not :tempids

sova-soars-the-sora 2017-11-17T17:35:37.000432Z

Ah you are updating the whole atom with a delta and a merge function to handle it. Cool. Mmm, you need to have tempids... I'm gonna say: ask in the #om channel, I think there is a placeholder function but i'm not sure. Your database could push tempids across the wire with the data update, but again someone more experienced in #om will be able to set you straight faster

sova-soars-the-sora 2017-11-17T17:41:29.000635Z

@daniel.dyba for all my inserts into the atom I use a specific mutate function for each attribute branch in the atom.... Have you tried just using an underscore for tempids ?

sova-soars-the-sora 2017-11-17T17:41:47.000220Z

_

@sova I thought underscores only work when you’re destructuring. Are you suggesting using an underscore as a return value?

sova-soars-the-sora 2017-11-17T17:44:54.000532Z

destructuring yes, not as a return.

@sova I copied my question to the #om channel too

@sova Right, but Line 2356 expects a return value for :tempids

sova-soars-the-sora 2017-11-17T17:46:01.000002Z

oh good. yeah they might take a little while but the experts live there. hmm so can you show me the way you're invoking this, maybe I can help more

you can’t use destructuring at this point

sova-soars-the-sora 2017-11-17T17:46:29.000321Z

mmm right

sova-soars-the-sora 2017-11-17T17:47:00.000039Z

So you have a remote specified, and therefore it is trying to get your tempids

clojure
;; where on is a reference to om.next
  (def reconciler (on/reconciler
                   {:state m/init-data
                    :parser parser
                    :send (m/send-to-chan send-chan)
                                        ; FIXME: We're missing a merge function that does a custom merge on the data
                                        ; we get back from the server
                    :merge (fn [reconciler state delta query]
                             {:keys []
                              :next state
                              :query nil})
                    ; it should return a map with the keys: :keys, :next, :tempids
                    ; what's the purpose of tempids???
                    :remotes [:list-models]}))

there’s more code to this obviously, but this is the heart of the matter

sova-soars-the-sora 2017-11-17T17:48:46.000614Z

i think you can just generate some tempids for this specific task, they don't need to be anything special .. i think the way this is normally done is with [in your case] on/tempid

sova-soars-the-sora 2017-11-17T17:49:57.000560Z

because it needs a fake index as it's moving them from the database into the atom, is my understanding.

Right, but do I generate one? Do I generate the number equivalent to the count of the list I get back from the server? And what data structure is tempids?

Suppose the response from the server is:

{
  "model": {
    "items": [
      "A",
      "B",
      "C"
    ]
  }
}

Then that response is captured here:

(defn model-list-loop
  [c]
  (go-loop [cb (<! c)]
    (let [results (<! (reg/list-models))]
      (cb {:list/model-names (get-in results [:model :items])}))
    (recur (<! c))))

Where results is the map that represents the above server response

sova-soars-the-sora 2017-11-17T17:53:31.000320Z

and you're looping over all your remotes there?

model-list-loop is called immediately after the reconciler is defined

sova-soars-the-sora 2017-11-17T17:58:52.000225Z

Om.next has an internal representation for stuff in the atom, which is where I think tempids come in.

sova-soars-the-sora 2017-11-17T18:00:28.000178Z

For every new transaction you need to have a tempid, but I don't know to be honest, i never used merge to update to the atom. except for those snippets i showed you. I think just one tempid per transaction (like the ones you see in the javascript console) is sufficient

sova-soars-the-sora 2017-11-17T18:01:42.000701Z

you've probably seen this video but at around 19:43 he goes into tempids

sova-soars-the-sora 2017-11-17T18:01:57.000174Z

19:35 *

sova-soars-the-sora 2017-11-17T18:02:27.000271Z

anyway, good luck dude, sorry i couldn't be more help 🙂

@sova thank you for taking the time to answer my questions!