Fork me on GitHub
#fulcro
<
2019-02-04
>
hmaurer15:02:49

I am having a strange issue with how idents are looked up in the application I am working on. I cooked up a minimal example to reproduce the issue:

(def app-db
  {:nested {:unit {:task [:task/id 1]}}})

(prim/db->tree [{[:nested :unit] [{:task [:task/name]}]}] {} app-db)
; => {[:nested :unit] {:task [{} {}]}}
Note the vector with two empty maps under task. Why is that? I investigated some alternative scenarios:
(def app-db
  {:task [:task/id 1]})

(prim/db->tree [{:task [:task/name]}] {} app-db)
; => {}
(as I would expect)
(def app-db
  {:nested {:unit {:task [:task/id 1]}}
   :task/id {1 {}}})

(prim/db->tree [{[:nested :unit] [{:task [:task/name]}]}] {} app-db)
; => {[:nested :unit] {:task {}}}

hmaurer15:02:27

Actually, I have an idea of what might be going on: when the table doesn’t exist, Fulcro thinks of the ident as a vector of elements and performs the join on that? But if that’s the case, it begs the question: is there a way to tell Fulcro “no, treat this as an ident”? (beyond creating the table in the database, like I did)

hmaurer15:02:32

This wouldn’t explain why my second example behaved the way it did though:

(def app-db
  {:task [:task/id 1]})

(prim/db->tree [{:task [:task/name]}] {} app-db)
; => {}

hmaurer15:02:33

And could someone point me at the place in the codebase where Fulcro resolves idents please? 🙂

currentoor19:02:26

@hmaurer the only way for fulcro to know if something is an ident/join is if there is a component with an ident involved

currentoor19:02:52

when you do {:some-k (prim/get-query ChildComponent)] in a parent component, when building it’s query, fulcro tacks on some meta data on the query, specifying that it is in fact a join with such and such ident so look there

currentoor19:02:45

when you pass in a query by hand, like you’re doing there is no metadata, so fulcro doesn’t notice the join

currentoor19:02:24

you need to call db->tree like so (prim/db->tree (prim/get-query SomeComponent) ...)

currentoor19:02:09

and yes you need to have a :task/id table

hmaurer19:02:05

Ah, interesting. Thanks @currentoor!

currentoor19:02:25

for example i have this component with this structure

currentoor19:02:27

ui.cljs:307 (prim/get-query OrderSummaryModal) => [:order/id
 :fulcro.incubator.pessimistic-mutations/mutation-errors
 {:order/payments
  [:payment/id
   :payment/amount
   :payment/change
   :payment/kind
   :payment/cc-pan 
   :payment/created-at 
   :payment/cc-brand]}]

currentoor19:02:43

that’s the query

currentoor19:02:50

and here’s the meta

(meta (prim/get-query OrderSummaryModal)) => {:component ucv.ui.mobile-pos.payment-flow.ui/OrderSummaryModal,
 :queryid "ucv.ui.mobile-pos.payment-flow.ui/OrderSummaryModal"}

hmaurer19:02:06

why does Fulcro need this metadata?

currentoor19:02:24

so from the meta data fulcro can get the component class

currentoor19:02:43

and from that it can figure out what the ident key is (if it’s an ident component)

currentoor19:02:17

otherwise fulcro has no way of knowing if it’s a join and what the ident key/fn is

currentoor19:02:55

because even though we usually make an id type key the ident key/fn it doesn’t have to be

currentoor19:02:01

it’s totally arbitrary

hmaurer19:02:14

wouldn’t it know it’s a join by the syntax of the query? i.e. {:some-field ...}

currentoor19:02:16

you could make an ident key out of :foo/name

currentoor19:02:51

that’s a nested query yes, but it doesn’t know that it’s a join vs a nested query

hmaurer19:02:09

Ah, I see what you mean

currentoor19:02:49

i’ll make a quick example

currentoor19:02:47

;; this query
[:title {:child [:id :name]}]

;; can be satisfied by this
{:title {:child {:id 1 :name "foo"}}}

;; or can be satisfied by this
{:title       [:child/by-id 1]
 :child/by-id {:id 1 :name "foo"}}

currentoor19:02:01

the meta data tells fulro that it’s the latter you want

hmaurer19:02:12

@currentoor oh right. I’ll play a bit with this / check the metadata on queries

hmaurer19:02:20

thanks for taking the time to write this down