Fork me on GitHub
#keechma
<
2016-04-25
>
mihaelkonjevic04:04:00

@roberto: you can add meta data on collections and named items

roberto12:04:14

thanks, it is what I ended doing.

roberto12:04:15

the :recordings :current entity is being attached some meta data. I noticed this overwrites the meta data for :recordings :list.

roberto12:04:20

is that the expected behavior?

mihaelkonjevic12:04:11

that shouldn’t be happening. I’ll investigate and get back to you

roberto12:04:56

oh, I think I know why, because the entire app-db-atom is being reset!

roberto12:04:17

is there a way to just update it instead of resetting?

mihaelkonjevic12:04:58

but ti should return the whole new version of atom with only the (relevant) part of the data changed.

roberto12:04:47

hmmm, for me it is changing the entire atom, deleting the :list and only :current is present

mihaelkonjevic12:04:05

it deletes only the meta data or the data too?

mihaelkonjevic12:04:25

also how are you retrieving the meta data in your ui component?

roberto12:04:28

I’m using get-collection-meta

mihaelkonjevic12:04:34

yeah, that’s the right way

roberto12:04:47

but only for troubleshooting, was wondering why my list disappeared when I selected an item

mihaelkonjevic12:04:14

that definitely shouldn’t be happening

mihaelkonjevic12:04:15

you are seeing this behavior only in your app or in place-my-order app too?

roberto12:04:52

i haven’t tried place-my-order, planning on doing that today. Seeing it on my app right now, which is tightly based on place-my-order

mihaelkonjevic12:04:08

can you paste the code that shows that behavior?

roberto12:04:15

I have a list on the left side, and the selected item is displayed on the right side

roberto12:04:28

1 second, they are two controllers

roberto12:04:21

this is the function in the controller for displaying the individual item:

(defn update! [app-db-atom updater]
  (reset! app-db-atom (updater @app-db-atom)))


(defn load-recording
  [app-db-atom slug]
  (update! app-db-atom
           #(edb/insert-named-item % :recordings :current {} {:is-loading? true}))
  (let [recording (edb/get-item-by-id @app-db-atom :recordings (js/parseInt slug))]
    (when-not recording
      (go
        (let [req (<! (http/get (str "/api/recordings/" slug)))
              meta {:is-loading? false}
              [success data] (unpack-req req)]
          (update! app-db-atom
                   #(edb/insert-named-item % :recordings :current data meta)))))))

roberto12:04:46

this is the what loads the list:

(defn load-collection
  [entity list app-db-atom req]
  (do
    (reset! app-db-atom
            (edb/insert-collection @app-db-atom entity list [] {:is-loading? true})))
  (go
    (let [[is-success? body] (unpack-req (<! req))
          data               (if is-success? (:recordings body) [])
          max-pages         (.ceil js/Math (/ (:total body) page-size))
          meta               (if is-success?
                               {:is-loading?  false
                                :current-page (:current-page body)
                                :total        (:total body)
                                :max-pages    max-pages
                                :next-page    (next-page (:total body) max-pages (:current-page body))}
                               {})]
      (reset! app-db-atom
              (edb/insert-collection @app-db-atom entity list data meta)))))

(def load-recordings (partial load-collection :recordings :list))

roberto12:04:12

this is the list controller:

(defrecord Controller []
  controller/IController
  (params [_ route]
    ;;Only run this controller when the route is home or "recordings".
    (let [route-data (:data route)]
      (when (or (and (= (:section route-data) "recordings")
                     (:page route-data))
                (= (:section route-data) "home"))
        route-data)))

  (start [this params app-db]
    (if (= "home" (:section params))
      (controller/redirect this {:section "recordings" :page 1})
      (when (:page params)
        (controller/execute this :load-recordings params)))
    app-db)

  (handler [_ app-db-atom in-chan out-chan]
    (go (loop []
          (let [[command args] (<! in-chan)]
            (case command
              :load-recordings (let [url (str "/api/recordings?page=" (:page args))
                                     req (http/get url)]
                                 (load-recordings app-db-atom req))
              (get-collection app-db-atom))
            (when command (recur))))))

  (stop [_ _ app-db]
    (edb/remove-collection app-db :recordings :list)))

roberto12:04:33

the default case is just this:

roberto12:04:36

(defn get-collection
  [app-db-atom]
  (prn "METAS: " (edb/get-collection-meta @app-db-atom :recordings :list))
  (prn "COLLECTION: " (edb/get-collection @app-db-atom :recordings))
  (edb/get-collection @app-db-atom :recordings :list))

roberto12:04:51

which i placed there because my list kept disappearing

mihaelkonjevic12:04:05

this line won’t return anything (prn "COLLECTION: " (edb/get-collection @app-db-atom :recordings))

mihaelkonjevic12:04:16

because you need to give the name of the collection

mihaelkonjevic12:04:31

if :recordings is the entity name

mihaelkonjevic12:04:42

you need to pass the :list as the collection name too

roberto12:04:51

even if I give the name of the collection, it returns an empty list

roberto12:04:18

this is the controller for the selected item:

(defrecord Controller []
  controller/IController
  (params [this route]
    (let [route-data (:data route)
          page       (:section route-data)
          slug       (:slug route-data)]
      (when (and (= page "recordings")
                 (not (nil? slug)))
        route)))

  (start [this params app-db]
    (let [slug (get-in params [:data :slug])]
      (controller/execute this :current-recording slug))
    app-db)

  (handler [this app-db-atom in-chan out-chan]
    (go (loop []
          (let [[command args] (<! in-chan)]
            (case command
              :current-recording (load-recording app-db-atom args)
              :backup-to-vimeo (backup-to-vimeo app-db-atom args)
              nil)
            (when command (recur)))))))

roberto13:04:18

for what it’s worth, I think it is because of the update! function

roberto13:04:31

it is using reset! which, well, will replace the entire atom

mihaelkonjevic13:04:56

yeah, but it should update just the part of the internal map. I’ll definitely have to check what’s going on

mihaelkonjevic13:04:29

btw you can shorten the code inside the handler functions by using the dispatcher function https://github.com/keechma/keechma-todomvc/blob/master/src/keechma_todomvc/controllers/todos.cljs#L28

roberto13:04:45

ah, and the update! function in that example is using swap! instead of reset!

roberto13:04:47

will try that

mihaelkonjevic13:04:33

I’m not using EDB in that app

mihaelkonjevic13:04:22

EDB has it’s own internal structure which is why I’m replacing the whole atom

roberto13:04:29

I’m probably understanding something wrong, isn’t app-db-atom completely replaced with a new value by reset!? Or is this not a typical clojure atom?

mihaelkonjevic13:04:06

it is, but the map inside should retain the old data.

mihaelkonjevic13:04:30

it seems that edb is removing some data it shouldn’t

roberto13:04:16

yeah, if I reach into the atom manually, I can see the list there

roberto13:04:29

(:entity-db @app-db-atom)

mihaelkonjevic14:04:50

@roberto I think this part is the problematic

mihaelkonjevic14:04:27

it seems that you’re calling get-collection before load-recordings is finished

roberto14:04:51

get-collection is supposed to be the default case

roberto14:04:08

so, when an item is selected load-recordings shouldn’t be called, because it is already there

mihaelkonjevic14:04:09

but you load only one item when the item is selected, right?

mihaelkonjevic14:04:30

so basically what needs to happen is: both controllers need to load their data, list and current

mihaelkonjevic14:04:37

and they will be merged inside the EDB

mihaelkonjevic14:04:53

so you will always have only one version of the current recording

mihaelkonjevic14:04:11

but, you still need to load the collection :list and named item :current

mihaelkonjevic14:04:05

which is different from the place-my-order app

mihaelkonjevic14:04:14

because it doesn’t have the master-detail view

mihaelkonjevic14:04:25

it’s either the list of restaurants or one restaurant

mihaelkonjevic14:04:21

do you see both requests (list and current) in the console when you have the detail page open?

roberto14:04:43

what do you mean by ‘requests’?

roberto14:04:46

xhr rquests?

roberto14:04:00

no, it is not supposed to issue an xhr request

roberto14:04:07

because it is already loaded.

roberto14:04:19

so the flow is the following: initial view displays the master list, that does an xhr request

roberto14:04:43

then when we select an item from that list, we don’t do any xhr requests because the items are already downloaded

mihaelkonjevic14:04:29

oh, there’s another problem I just noticed

mihaelkonjevic14:04:37

you’re returning the whole route-data

mihaelkonjevic14:04:43

from the params function

mihaelkonjevic14:04:54

which causes the controller to be restarted

mihaelkonjevic14:04:13

controller manager checks what is returned from the params function

roberto14:04:14

hmmm, so what should params return?

roberto14:04:24

Receives the route-params and returns either the params for the controller or nil

mihaelkonjevic14:04:25

only the subset of data your controller cares about

mihaelkonjevic14:04:54

this seems to be a documentation issue.

mihaelkonjevic14:04:50

basically, controller checks what is returned from the params function

mihaelkonjevic14:04:01

and based on that decides what to do with the controller

mihaelkonjevic14:04:15

Whenever the URL changes, the manager controller will do the following: It will call params function of all registered controllers It will compare returned value to the last returned value (returned on the previous URL change) Based on the returned value it will do the following: If previous value was nil and current value is nil it will do nothing If previous value was nil and current value is not nil it will start the controller If previous value was not nil and current value is nil it will stop the controller If previous value was not nil and current value is not nil but those values are same it will do nothing If previous value was not nil and current value is not nil but those values are different it will restart the controller

roberto14:04:33

ok, this is helpful