This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-11-17
Channels
- # aws (3)
- # beginners (81)
- # boot (155)
- # capetown (2)
- # cider (32)
- # clara (14)
- # cljs-dev (40)
- # cljsrn (12)
- # clojure (158)
- # clojure-austin (5)
- # clojure-korea (6)
- # clojure-poland (1)
- # clojure-russia (63)
- # clojure-spec (45)
- # clojure-uk (75)
- # clojurescript (109)
- # code-reviews (1)
- # core-logic (12)
- # core-matrix (1)
- # cursive (36)
- # datomic (16)
- # defnpodcast (1)
- # devcards (2)
- # editors (3)
- # euroclojure (1)
- # events (3)
- # flambo (1)
- # hoplon (19)
- # javascript (4)
- # jobs (1)
- # lein-figwheel (4)
- # leiningen (1)
- # off-topic (1)
- # om (177)
- # onyx (121)
- # pedestal (14)
- # planck (19)
- # proton (3)
- # re-frame (36)
- # reagent (21)
- # remote-jobs (1)
- # ring (4)
- # ring-swagger (6)
- # spacemacs (1)
- # specter (2)
- # test-check (4)
- # untangled (9)
- # utah-clojurians (1)
- # yada (2)
@isak Sounds great! Is the parser open source? If not, is there any example for usage, so I can learn to write myself.
@doglooksgood: its not open source, because it is written in f# (.NET), so there probably wouldn't be enough interest to warrant the effort, but i can give a couple of examples
1) simple example with multiple 1-to-1 joins: http://i.imgur.com/P7heGui.png
More complex example that includes a 1-to-many join, and also search conditions: http://i.imgur.com/WK9xOYR.png
the strategy i took was 1) parse om query 2) generate a query plan from om query 3) translate om query to a SQL syntax tree 4) render sql from syntax tree 5) execute sql 6) use query plan to know how to read the results back into the right shape
and then i have another place with metadata about joins: 1) from table 2) to table 3) join name 4) join condition
thats actually a custom thing, because search conditions other than idents are not part of the grammar
but, it seems your client have the fully control to the query? is there any server-side part? I mean, some idea like: client decide the data they want, and server decide the entities they can provide?
here is the grammar from om next: https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L15-L23
yes for us the client fully specifies everything. the only thing controlled by the server is permission checking, and which company the query is relative to
for permission checking, we check both at the row level, and at the column level (also for the search conditions)
but thats not really necessary, because you need to do everything in stages anyway, and can choose to add/remove search conditions for the sql on the server
in the second example, i have :top, which is the sql server equivalent of limit in postgres
:top is pretty easy, except when your query includes a 1-to-many join, in which case you have to be careful not to chop off child records if there is a limit
Really struggling with how to handle authentication with compassus. I created a Wrapper component and have a (when token (factory props))
in render. Trouble is, it is trying to read the query for the route before I've authenticated. @anmonteiro any advice on how I should do this? How should I delay the read until after I have fired a login request and received a token?
My only idea is to have two separate apps and mount one or the other, depending on whether im authenticated.
I see if I don't set route-dispatch: false
I can add a read method that dispatches on the route, perhaps I can use this to change behaviour based on whether I'm authenticated or not?
@danielstockton :route-dispatch false
could probably help but you still need to read after you have authenticated
that follow-on read could either be done in merge!
or by transact!
ing a key to read
I tried adding a key to read at the end of the transact, but it doesn't trigger the read. Perhaps because it isn't a key in the wrapper's query?
The Wrapper is re-rendering after the transaction, but doesn't seem to be re-reading the query for the route
@danielstockton are you on 1.0.0-alpha2?
alpha1
try upgrading and see if it works 🙂
I also tried with :route-dispatch false
and adding my own read function for the route, I got into a muddle with user-parser, ast, route, query....
Ok, i'll try 🙂
specifically: https://github.com/compassus/compassus/commit/d3a0b4523bcb3ffd6006ef6d46c4d0b6e53f028c
Nope 😞
Tried different keys after transact, the route key and the key in the query of the route view
can you put together a minimal repro I can look at?
I don't think there's a bug in Compassus anymore, might be related to your app
but still
Ok, i'll try to do that
thanks!
This shows the idea: https://gist.github.com/danielstockton/cb3a26c7dc1768f895956c2e2cfc77bc Need to set it up in a new project and try to run it, maybe you can spot something clearly amiss
@danielstockton maybe. try putting it in didMount instead?
No difference. Am I right with the key I'm passing to transact (:index), or should I be passing a key in the child component query?
:index
doesn't mean anything to the Indexer
you should be queueing :user/token
for example
but I think merge!
will queue that automatically hrm
well I have a custom merge fn on the reconciler
I did try the other keys though
make sure you return :keys
from your custom merge
i only customized merge-tree actually, and its using a simple clojure merge
if your gist exhibits the problem I'll try it out and let you know
ok, ill try to test it
you're probably safe, i can't reproduce it 🙂 i'll try to find out why
it works in my test case, at least when i pass a key to transact
main difference is that there's no ajax call
you can try a setTimeout
or something
works perfectly with a 5 second timeout too, nevermind, ill keep digging
I found the problem. I'm not sure how to access the app-state in the send function, so I was setting an atom with the token value and firing the request when the token was present. Due to the asynchronous nature, I was trying to fire the request before i reset that atom with the token...
Is there a better way to do this? I think I need to modify the read function to pass the token through to send somehow
@danielstockton can't you send the token as a param in the query?
you can attach the token to the AST and read it back in your send function
Probably, I haven't quite got to grips with the parser yet.
My query looks like [:totals]
in send at the moment and my read function is:
(defmethod read :totals
[{:keys [state ast] :as env} key params]
(let [st @state]
{:api true
:value (get st :totals)}))
Instead of :api true
I need to do something with the ast and pass that?
cljs.user=> (om/ast->query (assoc (p/expr->ast :totals) :params {:token "xxx"}))
(:totals {:token "xxx"})
so in short you just need to (assoc ast :params {:token "foo"})
Ok great, i'll try that, thanks
Query question: I am trying to pivot a vector. What I have is one entity (with rendering component) with an array of owners, and I would like to also have the array of owned when rendering the owners.
I am trying to just even query the db directly right now but even that is failing me.
perhaps an example would help
{:players [{:name "me"}
{:name "other guy"}
{:name "them"}]
:companies [{:name first :owners ["me" "other guy"]}
{:name "second" :owners ["me "them"]}]}
I am looking to get an result for "me" that contains "first" and "second" and a result for "them" that contains "second"
At this point I don't really even care much about the form of the result, just that it exists.
ultimatly, I would like to support duplicates in the :owners list, and retrieve a list of "me"s from each company, even it is was empty, but I can deal with that later
Something like:
[{:name "first" :owners ["me"]} {:name "second" :owners ["me"]}]
is what I really want. I have tried various forms of [{:companies [:name [:owners "me"]]}]
trying to get the [:field value] syntax to work for me, but failingThis: https://gist.github.com/danielstockton/ca8b8d7c1fbbe19f3674f6fd9cbe794f#file-test-cljs-L29 The read is happening before the token is merged into the state...I don't know how I can delay it.
Shouldn't any read-keys be read after the state has been updated?
@danielstockton looking now
can you describe the problem you're having?
With the when-let
above, the read never happens because token is always nil
. I'm mutating a token on to state and telling it to re-read :user/name
afterwards, it seems that read happens before token is merged onto the state
Somehow, I need to wait until state has a token and then re-trigger the read...
Or rethink what im doing
right but is :user/name
coming from the remote?
@danielstockton the re-read won't go back to the remote, if that's what you want
Om Next won't queue a 2nd remote call if you specify :user/name
to be re-read
you need to do a 2nd transaction for that to happen
does this sound like the problem you're having?
yep, it does
how should i trigger a second transaction to trigger the remote read? i have two remote reads, getting the token and then using the token in an ajax request
@snoonan it's unclear to me what your real problem is. I think you just want to query for [{:companies [:name :owners]}]
but filter the parser result based on some "name" parameter
@danielstockton I think the easiest way is to override :merge
in the reconciler
even if it doesn't re-read from the remote, it doesn't also call the read function?
i have a print in there and it doesnt seem to trigger it, which implies it doesnt do any kind of read?
what read function?
defmethod read :user/name
?
here: https://gist.github.com/danielstockton/ca8b8d7c1fbbe19f3674f6fd9cbe794f#file-test-cljs-L30
this print is never triggered, even though i tell the transact to re-read :user/name
I see a println
println, yep
I see it printing, is what I meant
let me try a lein clean and restart figwheel..
maybe it didnt properly update to alpha2
still not working for me 😕 what can that be
I don't know... Om / ClojureScript version?
oh boy, i had a typo in my :clean-targets
still doesnt work though
[org.clojure/clojure "1.8.0"] [org.clojure/clojurescript "1.9.293"]
om alpha47
hrm, I might have pasted an outdated version of your gist. I don't see the printing after all 🙂
you're not crazy!
@danielstockton I think I got it
your :user/name
read is not getting triggered
but your default read is
which makes sense because the only thing that's queued for re-reading is :user/token
, not :user/name
Another way of asking, how would you do 2d normalization. Each cell is a cross of owner and company and represents a portion of ownership (10% in my case).
if you normalize your state, both owner and companies will get the relevant data (the ones matching component Idents) normalized
@anmonteiro what about the :user/name key after the transact!
should that not trigger a :user/name read?
yeah, it's triggering a :user/name
read
but that read happens before the remote has responded
yeah, this is my problem
My trouble with accomplishing that is I don't have a good name (Ident) that both can use. I'll try to figure out something that will work. Thanks
what you need to do is add :user/name
to :keys
in the reconciler's :merge
function
so that it gets read after the remote result returns
do you have an example of something similar?
there's something else you can do too
you can use the :value {:keys ...}
that your remote mutation returns to auto-queue them automatically in an overridden merge function
this way if you add {:value {:keys [:user/name]}}
to your 'user/login
mutation on the server, merge
will know to re-read those because they arrive in the remote result too
I'm afraid I don't have a concrete example to show you, but Compassus does something with :keys
in merge which maybe can give you some insight into how it works: https://github.com/compassus/compassus/blob/master/src/main/compassus/core.cljc#L295-L298
in my case, every remote read should be re-read once I have a token and adding all the keys from the remote doesn't seem nice
it should re-read the query for the current-route, in the general case
i only have :user/name
for now but this is the simplest case
that's something you can also do easily
you have the reconciler and the state in merge
so you can get the current route, and obtain the query of the component which pertains to that route
and then just update :keys to be that query?
not quite 🙂
if the query is all keywords, then yes
if not you need to extract their "dispatch-key"
right, so query->ast and map :dispatch-key
e.g. {:some/join [:foo :bar]}
-> :some/join
(map (comp :dispatch-key om.next.impl.parser/expr->ast) query)
something like this ^
mhm, thanks
i'll see what i can work out
What could be the reasons for the (str "No queries exist for component path " cp " or data path " path’)
exception?
we have one read-key, that when added in a transaction which makes most of the app re-render and throws this exception at the (full-query component)
call of a leaf component
I see this quite a lot, is there a reason to prefer (update-in [:keys]
over (update :keys
?
@anmonteiro https://gist.github.com/danielstockton/ca8b8d7c1fbbe19f3674f6fd9cbe794f#file-test-cljs-L48
It looks like {:keys [:user/name], :next {:om.next/tables #{}, :compassus.core/route :index, :user/token token}, :tempids {}}
, still not seeing :user/name being re-read
I think there should be a style/indent
metadata on defui
.
For Emacs users, without any customize, this can provide a comfortable indentation, rather than this:
(defui Person
static om/Indent
(indent [{:keys [name]}]
[:person/by-name name]))
people always prefer following I think
(defui Person
static om/Indent
(indent [{:keys [name]}]
[:person/by-name name]))
the style/indent
should be [1 :form :defn]
.I got it working, now I have the remote read problem (doesn't trigger a remote read but the read function is triggered)
agreed @doglooksgood 🙂
@anmonteiro why exactly doesn't a re-read trigger a remote read? and how can i trigger that with a transact! ?
@danielstockton I could be wrong but I think re-read does trigger another remote read if the read returns a remote key-key with true or an AST
You can trigger that with a transact by mutating and specifying the key that should be re-read IIRC.
@danielstockton because it could introduce loops
if your re-reads trigger remote reads, then they'll be re-read over and over in a loop
I see.
Is there nothing special about a reread from a mutation compared to a normal read
I mean, can a distinction not be made somehow
Hey #om, I’m quite new here so please excuse me if this is not at all the right place for this. I'm trying to do some leg work into investigating some performance issues in FireFox over at CircleCI.
Has anyone here seen instances where Om Next triggers a requestAnimationFrame
or a bunch of Non-incremental GC
actions and FireFox siezes, dropping the FPS down to 0...for like 20 seconds.
I'm curious if anyone has run into a similar issue with using Om/Next in FireFox. I've done profiling side by side in Chrome and it is unhappy with a few little things but it doesn't seem to even blink at the load. It also has a GC spike but it takes 300 ms vs 20 s.