This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-10-22
Channels
- # bangalore-clj (2)
- # beginners (22)
- # boot (8)
- # cider (1)
- # cljs-dev (10)
- # clojars (1)
- # clojure (5)
- # clojure-austin (14)
- # clojure-conj (1)
- # clojure-dusseldorf (6)
- # clojure-france (3)
- # clojure-russia (11)
- # clojure-spec (3)
- # clojure-uk (2)
- # clojurescript (27)
- # datomic (4)
- # hoplon (68)
- # leiningen (7)
- # off-topic (1)
- # om (68)
- # onyx (12)
- # other-languages (1)
- # re-frame (19)
- # vim (2)
i finally figured out what my problem with process-roots
was: it only seems to work on join queries, not even on a flat [:prop] query. is there a reason for that or is it just missing functionality?
I'm integrating compassus in our app, my approach was to use an App wrapper component, with a query for global state, and read methods for our routes that'd just recurse with the parser like:
(defmethod client-read :route/home
[{:keys [parser query] :as env} _ _]
{:value (parser env query)})
I was hoping this would let us have compassus' routing sit on top of our current component/parsing structure, but the above doesn't work.
While the queries on App work as expected, our Home component -- which has a link query like [{[:current-user '_] [:db/id :foo]}]
-- is now parsed into these props {[:current-user '_] {:db/id 123 :foo "bar"}}
, when it used to be {:current-user {:db/id 123 :foo "bar"}}
@jfntn you’ll only get [:current-user _]
in props if you don’t use db->tree
links are supposed to be used with normalization
I’m using it, :current-user
falls back to our :default
reader which is:
(defmethod client-read :default
[{:keys [state query] :as env} k _]
(let [st @state]
{:value (om/db->tree query (get st k) st)}))
@jfntn can you put a minimal repro together then? could be a compassus bug
should be easy to create one
I’d really appreciate more docs on remotes and :send. What is a remote mutate allowed to return? Just {:value {:keys []}}
? I assume it ignores :action
?
Is there a way to send back “error” data with a remote mutate, e..g “you aren’t allowed to do that”?
I could list an extra key to be read, but then I’d need to store it on the server until the next time the user reads, which seems annoying and anti-scalable
@arohner IIRC there’s a :result
key that’s returned in the mutation response
anyway, a remote mutation’s response is a map, you can add whatever you’d like to it
it’ll get thrown away when merging back to the local app state, but you can change that behavior
@anmonteiro by replacing :merge
in the reconciler?
@arohner also note that you don’t necessarilly need to reimplement merge when overriding it, what I commonly do is call om.next/default-merge
and do my custom stuff
the default-*
functions are public vars for a reason
@anmonteiro wrote this gist to illustrate the problem: https://gist.github.com/julienfantin/dc3d1bf89edfbacc1447331bf851ce97
@anmonteiro not sure if this is a good idea, but I made my merge recognize transacts in :keys, and just call om/transact on everything returned
so now on the server, I just return {:value {:keys [(foo/error :text “an error”)]}}
from a mutation
@arohner right. one thing I forgot to mention is that whatever you return from the :action
thunk will be assoc
ed to the returning response under :result
maybe I should have started there, apologies 🙂
this is the code path: https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L291
wait, I mean the mutation that’s executed on the server
I suppose that’s what we’re talking about
my original goal was, given the client does a transaction that goes to the server, change client state in a different key, to signal errors, etc
^ here’s a server mutation example for a talk I gave at a meetup
so if the server knows it’s an error, return that from the :action
thunk, say {:error :nuke/wrong-code}
and the server will return that to the client
so your merge will receive something like {‘launch/missiles {:result {:error ::nuke/wrong-code}}}
nop it just throws it away
which is why you need to override :merge
so then I modified my merge to walk {:value {:keys []}, and om/transact on the client anything that looks like a transaction
right, but remember that those transactions could in theory send to the server again an enter a loop
it’s up to you to prevent that ofc
@arohner so what you could do is just swap!
to the state directly, or only support a predefined set of mutations that are guaranteed to run locally
@jfntn thanks, I’ll have a look soon!
@anmonteiro thank you, added a bit of context in the ns docstring!
@anmonteiro one weirdness I just noticed: it seems like the return value of remote mutations is getting merge
d into the client state, even when using default-merge
note that in default-merge, :keys
calls remove symbol?
, but the next state, which is reset! to the value of :next, merges everything in
@arohner the return value of mutations will be merged into the app state, yes
that’s normal, but note that tempid migrations will clear that “garbage"
maybe I’m doing something wrong then. I have a mutation that returns {:value {:keys}}. So then the return value is {‘foo {:value {:keys []}}
so when I manually inspect my app-state atom, I see {:foo “”, :bar “”, ‘foo '{:value {:keys []}}}
right, but that’s supposed to happen
the default-merge
merges every remote result into the app state
even mutations
components are responsible for updating IQuery/query
to contain all of the items their child components need?
@jfntn so this actually looks more like a Om bug
here’s a truly minimal repro:
(require '[om.next :as om])
(def p (om/parser {:read (fn [_ _ _]
{:value 42})}))
(p {} [{:foo [:bar]}]) ;; => {:foo 42} <- expected
(p {} [{[:foo/by-id 0] [:bar]}]) ;; => {[:foo/by-id 0] 42} <- yup
(p {} [{'[:foo/by-id _] [:bar]}]) ;; => {[:foo/by-id _] 42} <-- hrm?
I’ll get to that tomorrow