Fork me on GitHub
#om
<
2016-07-08
>
cmcfarlen02:07:14

@dnolen: I created an issue for that PR. Thanks for taking a look!

cmcfarlen02:07:10

@jasonjckn: I've recently be working on client side routing and history. What I settled on was using bidi/pushy for routing/history management and using compassus for om routing. What I ended up doing was using om/transact! to do normal state management, but when time to navigate internal to the app I just used pushy to update the location and then loaded the app state from the url in the bidi callback. This works with the back button nicely and since my app is initialized from the url then deep linking is also supported (kinda) for free.

hlolli12:07:55

@jasonjckn: this works for one site I made.

(defn make-history []
  (doto (Html5History.)
    (.setPathPrefix (str js/window.location.protocol
                         "//"
                         js/window.location.host))
    (.setUseFragment false)))
and
(defonce history
  (doto (make-history)
    (events/listen goog.History.EventType.NAVIGATE
                   #(page-loader (get-subpage (.-token %))))
    (.setEnabled true)))
where page-loader is a function that mutates the app-state trough the reconciler. And get-subpage is a map that matches the uri parameter. (ps long time I implemented this, so not sure if this works like I think it does). Also this hack works because I change the uri according to page changes with:
(doto history
                          (.setUseFragment false)
                          (.setPathPrefix "")
                          (.setToken (name active-window)))
Here I don't used #uri so I need to tell Compojure about the website. Well, this is a ugly hack when I think about it.

anmonteiro14:07:44

re: your issue yesterday

cmcfarlen15:07:27

@anmonteiro: awesome! I wonder if this will cause some existing code to select different paths for existing unions if the unions are already just more specific sets.

anmonteiro15:07:15

@cmcfarlen: it will always select the most specific query

anmonteiro15:07:53

notice that I only call reduced in the strict case

anmonteiro15:07:35

so even if there’s a case that fits the relaxed one, it’ll run until it finds one that’s exactly equal

anmonteiro15:07:44

@cmcfarlen: I even wrote a test for that

cmcfarlen15:07:03

@anmonteiro: ah, yes. I see now. Very nice!

cmcfarlen15:07:34

@anmonteiro: I actually ran into another issue last night. I hope it will be the last as I have almost converted my entire app now. ha

cmcfarlen15:07:05

I had to add this in compassus-merge for merges after a remote mutate.

-    (om/default-merge reconciler state
-      (cond-> res
-        (not mutation?) (get route)) query')))
+    (assoc (om/default-merge reconciler state
+             (cond-> res
+               (not mutation?) (get route)) query')
+           ::route route)))

cmcfarlen15:07:24

err, actually, that isn't the right diff. Hold on

cmcfarlen15:07:36

Its the :next key that needs to have ::route assoc'd back in. I'm not saying that is a fix, just what I did initially.

cmcfarlen15:07:06

But ::route is being dropped after a merge! from a remote mutate coming back with :tempids and ref-based novelty. I also have to lookup the query for the current route and pass that along in the callback or the state is replaced with the response

cmcfarlen15:07:14

-    (om/default-merge reconciler state
-      (cond-> res
-        (not mutation?) (get route)) query')))
+    (update (om/default-merge reconciler state
+             (cond-> res
+               (not mutation?) (get route)) query')
+          :next assoc ::route route)))

cmcfarlen15:07:18

more like that

anmonteiro15:07:21

@cmcfarlen: hrm, I’ll look into that, thx for reporting

cmcfarlen15:07:52

@anmonteiro: Great! Thanks again. I can get more details together if you want

hlolli15:07:51

I'm still struggling with remote mutation. I'm using mutation to send email trough a server and I want the mutation to receive response if the email delivery went successful. I always end up with {send-email! {:result {:success? true}}} the name of the mutation is 'send-email!, how can I merge it into the app-state correctly. I can't access the response data in :action nor :remote?

anmonteiro15:07:11

@hlolli: override :merge in the reconciler

hlolli15:07:42

ok, had no clue to do that 🙂 nice

anmonteiro15:07:36

e.g.:

(defn my-merge
  [reconciler state res query]
  (om/default-merge reconciler state
    (if (symbol? (ffirst res))
      (-> res first second :result)
      res)
    query))

hlolli15:07:54

BINGO, I think I've read almost all documentation on om.next. But I see that there are some holes, so without slack I would be lost 🙂

cmcfarlen16:07:59

@hlolli: When you get to resolving tempids to stable ids from the server, the shape om expects is like: {'item/create {:tempids {[:item/by-id <#C06DT2YSY>/id[]] [:item/by-id 12312234]}}}

cmcfarlen16:07:35

So in that case you might have to move your novelty out to be beside the symbol in the map instead of replace it

cmcfarlen16:07:59

I ended up writing a fn to look for a :novelty key inside the returns from remote mutates and merge those in at the top.

hlolli16:07:57

ok, must admit I've never dived to tempids, but I'm still studying the talks code from anmonteiro. I know I will need to use them soon.

cmcfarlen16:07:07

It did take a while to figure out how that worked reading the om.next code so thought I'd mention it 🙂

hlolli16:07:35

A win win would be if you wrote a blog post about how you use it. Just throwing ideas out, no pressure 🙂

cmcfarlen16:07:28

A blog post at the very least, definitely

cmcfarlen18:07:28

@anmonteiro: after further digging it looks like default migrate is what is dropping the route, only if tempids are present. It does a db->tree->db cycle with the given query to add the tempids.

cmcfarlen18:07:18

So either the result has to have the shape of the root query, or something has to preserve those keys

anmonteiro18:07:43

@cmcfarlen: yeah, I was aware of that normalization cycle

anmonteiro18:07:23

just seems like I forgot to add the :compassus.core/route key after that

cmcfarlen18:07:22

(defn my-migrate
  ([app-state-pure query tempids]
   (my-migrate app-state-pure query tempids nil))
  ([app-state-pure query tempids id-key]
   (let [route (::compassus/route app-state-pure)
         res (om/default-migrate app-state-pure query tempids id-key)]
     (assoc res ::compassus/route route))))

cmcfarlen18:07:30

This seems to work

cmcfarlen18:07:44

It might be nice if compassus looked up the query for the current route and passed that along for merges with mutations. I might not be handling that properly though, so it might only seem nice 🙂

anmonteiro18:07:27

@cmcfarlen: this is definitely something that needs to be fixed in Compassus

anmonteiro18:07:32

I’ll try and look at it tonight

cmcfarlen18:07:14

Oh, don't spend a Friday evening on it! No rush, I just feel like its almost there.

jasonjckn21:07:38

what's the correct way to do a state rollback?

jasonjckn21:07:43

just reset! on app-state?

jasonjckn21:07:53

and om/from-history