This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-12-30
Channels
- # admin-announcements (42)
- # alda (8)
- # aws (10)
- # beginners (22)
- # boot (165)
- # bristol-clojurians (1)
- # cider (6)
- # clara (21)
- # cljs-dev (23)
- # clojure (74)
- # clojure-dev (8)
- # clojure-russia (41)
- # clojurescript (180)
- # core-async (11)
- # cursive (26)
- # datascript (2)
- # datavis (7)
- # datomic (29)
- # editors (1)
- # hoplon (7)
- # jobs (3)
- # ldnclj (4)
- # lein-figwheel (47)
- # leiningen (2)
- # mount (26)
- # off-topic (3)
- # om (163)
- # onyx (56)
- # proton (4)
- # reagent (6)
- # remote-jobs (1)
- # ring-swagger (4)
- # spacemacs (9)
@dnolen: When you get a minute, I'd like to know which internal thing is correct, and I'll try to fix the Om bug I reported. Should components that use a top-link like [:a _]
be indexed (when you build the index from root) by the ident, or just by the :a
keyword?
Wow, you can make a pretty powerful db remote using korma...
That covers picking fields, limit, offset, ordering and basic where clauses!
Hmm, I'm fallen quite flat trying to hook up a reader for my paramatised query. db->tree doesn't seem to like params. It's possible I've been misusing it.
https://github.com/olivergeorge/stripboard/blob/master/src/stripboard/client.cljs#L87
@olivergeorge: db->tree
does not understand parameterized queries - there’s no intention to change that. query parameters should no longer be present by the time you invoke db->tree
. They will either not be applied at all or should be applied on the result.
people that want fancier recursive querying will need to experiment on their own - this is what the Query AST is for
@dnolen thanks
Hi everybody ! I would like to ask one question about merging new state deltas into app-state. The format of the state delta which default-merge
(https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L1348, argument named res) expects seems to be little bit odd: {some/mutation {:tempids {[:key-path tempid] [:key-path real-id]}}}
is the correct form for the default-merge
to resolve tempids. But it doesn't pick state delta when it's nested in {some/mutation {:result some-state-delta}}
- so it's not possible to directly feed external (server) mutation parse result to merge!
function. It's possible only when we are parsing read expression or mutation which results in tempids... It's not particularly difficult to handle, but it seems little bit strange to me, am i missing something ?
For what it's worth. Not being applied would work fine for me (the params are applied server side, the client just needs to access the data). At the moment I think the presence of params means it returns nothing.
@olivergeorge: that's worth pondering. I thought about that too.
@dnolen: Btw, CONTRIBUTING.md (https://github.com/blog/1184-contributing-guidelines) might help bringing the contributing rules to everyone's attention.
@dnolen I gave that a go. Stripping out was easy. Seems helpful to me.
The next thing which caught me was handling a vector of maps. I expected my query [{:friends [:name]}]
to handle data in this format {:friends [{:name "anna"}{:name "bob"}]}
but there's no checking to differentiate between the value of :friends being a map and a vector.
That's not much harder to add.
(slightly fiddly actually since we're accumulating idents-seen
along the way)
I'll log tickets in case I'm on track and it proves a helpful reminder later.
@olivergeorge: the later is just a bug if true but I'm skeptical that's a showstopper bug. Do not report an issue without a minimal case.
@juhoteperi: yeah I'll probably copy the wiki there
@dnolen righto, thanks.
This is my minimal case:
(let [query [{:friends [:name]}]
data {:friends [{:name "anna"}{:name "bob"}]}
actual (om.next/db->tree query data data)]
(if (= data actual)
:good
[:bad {:expected data
:actual actual}]))
I get [:bad {:expected {:friends [{:name "anna"} {:name "bob"}]}, :actual {:friends [{} {}]}}]
@olivergeorge: that's not how db->tree works
Also I think that code has had changes since alpha28
I'll look again
(def state {:friends [[:friend/by-name "anna"] [:friend/by-name "bob"]]
:friend/by-name {"anna" {:name "anna"}
"bob" {:name "bob"}}})
(om/db->tree [{:friends [:name]}] state state)
@olivergeorge: FWIW this works for me ^^you need to use normalized data in db->tree
Thanks @anmonteiro. I just got there myself.
So requiring normalisation means I will need to define a client side schema using defui in order to use db->tree
@olivergeorge: exactly
in your example it would be something like:
(defui Friend
static om/Ident
(ident [this {:keys [name]}]
[:friend/by-name name])
static om/IQuery
(query [this]
[:name]))
(defui Friends
static om/IQuery
(query [this]
[{:friends (om/get-query Friend)}]))
Yeah, that's pretty much in my editor just now!
I was hoping not to have to do that. Seems like a lot of code. I wonder if denormalised could be supported or if it would get in the way.
@olivergeorge: you can use denormalized data if you like, nothing prevents you from doing that
just don't call db->tree
then
Gotcha.
deref state and access it directly
It's 95% of what I want but easy to copy/past and modify.
(really the recursive select-keys is what I want I guess... I'll go away and play)
Thanks for confirming for me.
I have a component which should render one particular entity. Should I use a JoinExpr
with IdentExpr
for the query like: '[{[:foos/by-id ?id] [:name]}]
?
Hard to say without knowing more but seems like you’d always want a component that just has the query for the attributes for which it should display. Then a parent component would do the job of selecting and providing a specific one. Is that not possible in your case?
In my case I like to show only one particular entity on a page. The URI would be /foos/123
.
In the list case, I have a list component which than uses a list item component as usual.
@akiel: from your description, the query looks okay
@akiel: hard to say more without looking at some actual code
@akiel I’ve been playing with this too, and that’s the query I came up with (still in progress, though). The only alternative I could see is to use params
Note the result of the query will then be something like {[:foo/by-id 1] {:name “Jon”}}
@jonsmock Yes I will also try params because I get the data back keys under [:foos/by-id 123]
which is hard to unwrap.
A slight tweak I can think of is to have the query param as the full [:foo/by-id 1] ref
I have now ’[({:foo [:name]} {:id ?id})]
and
(defmethod read :foo
[{:keys [state query]} _ {:keys [id]}]
(let [st @state]
{:value (select-keys (get-in st [:foo/by-id id]) query)}))
I’m pretty new still, but both seem reasonable to me. I don’t know what the trade-off is exactly.
I’m also new. I saw the IdentExpr
in JoinExpr
and thought that it would be useful in my situation.
Personally I’m trying to make the ref way work, but I think the params way is good for search results lists and things like that
I think going by the :foo
key for a particular foo and using :foos
for the list of all foos sounds reasonable.
I ended up using another different way to accomplish a similar thing. I created a function and returned and anonymous class and passed the id I wanted to render
(defn page*
[{:keys [id]}]
(ui
static om/IQuery
(query [this]
[{[:items id] query}])
Object
(render [this] (something))))
(def page (memoize page*))
since I couldn't figure out a non ast manipulating way to pass the id down from my router
Thoughts: 1. Seems like your using the ref query way, which is what @akiel was asking about 2. You’re creating a page for each item - how many items do you have?
I'm not sure i haven't run into problems with it so, far other than discovering i had to memoize the result so om could figure out the query-path to the component
@edpaget: I read the id directly from the location:
static om/IQueryParams
(params [_]
(:route-params (r/match-route (u/location-path))))
and this is simplified version of what i'm actually doing, there's just one specific thing in my om app that has pages like that
@akiel: i hadn't thought about doing it that way at all, nice. ! I was just trying to keep all the routing logic in my top-level component
@dnolen: David I have to you a couple of query and parameters https://gist.github.com/dark4eg/d7dc2364606fae3fb435 1. In the example described in gists, use get-query. In this case, I cannot set-query! with the new settings, so in reality have to simply duplicate the IQuery in components A and B 2. I have the IQuery component A to specify all the keys for remote synchronization and it turns out that when your application runs, stretch all the keys that say to me on the first page of the application does not need a list of employees. Is there a point above or I still have to live with that?)
@a.espolov ask questions to the channel please, thanks
@a.espolov: David meant don't direct the question towards him but to the channel; see the channel topic
I'm happy to help but I don't understand what you are asking
could you please rephrase?
@a.espolov: also, is Insps
in component A meant to be B ?
@a.espolov: if no one can answer you will just have to be patient - such is life
A question concerning tempids...
(defmethod mutate 'company/add-user
[{:keys [state ast]} _ params]
(let [tempid (om/tempid)
user (assoc params :db/id tempid)
local (assoc user :user/confirmed true)]
{:value {:keys [:users]}
:remote (assoc ast :params user)
:action (fn []
(swap! state update-in [:by-id] assoc tempid local)
(swap! state update-in [:users] conj [:by-id tempid]))}))
I need to know the tempid outside of the action to send it to the server with the same mutation, yet the above will not work, as it will generate multiple tempids. Any ideas on how to do this cleanly?Hm ok so i need a custom parse to achieve this? I mean generally i do not use the :result of client mutations.
I generate the tempid on the client, then send it off for resolving while storing it in the state
I’m going to repeat my last statement until you say something that clarifies what you are doing
Ok. But i also want to store the newly created object locally in some places and use it until it is resolved.
Yes, my question is only how to get the same tempid sent off to the server that is stored in the state.
Ok. I'll explain what i am doing and how it fails. I generate a tempid for a new object, say a user in a local mutation. I want to insert this new user into some collections as well as into my by-id collection (i use normalization). The mutation is remote as well to generate the object on the server. Datomic gives me back the real id and i send a map mapping the tempids coming from the client to the real ids and want to resolve them. But the tempids in the state are not the ones returned by the server for resolving, as they are generated outside of the action method. So different targets get different tempids.
Hm no already checked everything. The server resolves the same id that is requested to be resolved correctly. Why doesn't it make sense? Isn't the mutate called multiple times by the parser?
If this is so i have no idea how i could get what i am seeing - two different tempids, one sent, one written.
you create a tempid on the client, if the server returns a mapping from that to the new one it will work
OK but showing examples that obviously aren’t going to work don’t help me understand the problem
Sorry, i thought the description for my snippet made it clear. Will think about it again.
@smeister: something I do not understand is why you aren’t passing the tempid as a parameter to the mutation
Ok this would solve my problem. It just didn't seem that clear, as it should be an implementation detail which is better kept inside of the mutation. I'll do it that way now, thanks a lot.
well I can think of a couple alternatives - but they aren’t any simpler than just generating this when you invoke the transaction
@smeister: if it helps at all, here is minimal example of the tempid functionality (mocking the resolution of it but should work the same way from server) https://github.com/akmiller78/tut-omnext-tempids