Clojurians
#om
<
2016-03-18
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

bones03:03:33

Am I correct in thinking that there’s nothing inherently special about the query grammar; the “magic” comes from interpreting the use of that grammar in our readers in order to best traverse our data?

bones03:03:58

How off am I? a little or a way?

adamkowalski03:03:18

that sounds about right

adamkowalski03:03:45

his query section addresses that topic

bones05:03:21

Yeah, I’ve been through that a couple times, it’s a good read : )

denik11:03:12

@anmonteiro: do you have plans to extend om-css to work with sablono as well?

anmonteiro11:03:42

@denik: something to think about

anmonteiro11:03:49

Contributions welcome too!

dnolen12:03:02

@anmonteiro: you’re saying the first case is the bug, that the template should erase the union?

dnolen12:03:41

@anmonteiro: oh missed the later bits in that backlog - yeah bug

anmonteiro13:03:54

@dnolen: I ended up figuring it out by myself by looking at the query-template union tests

anmonteiro13:03:07

submitted issue #652 and PR #653 with the fix

dnolen13:03:49

great thanks

denik15:03:01

@anmonteiro: what about pseudo-selectors?

adamfrey16:03:57

has anyone written anything here or elsewhere about doing aggregation in an om.next query? Imagine a list of boards which each contain a list of todos, and your component wants to display each board’s name and percentage of todos complete. Any opinions on a clean way to handle that in the parser?

tomjack16:03:46

do you have more than one way in mind?

anmonteiro16:03:03

@denik: aren't they supported by garden itself?

anmonteiro16:03:23

if you've got a failing case, open an issue and I'll gladly look into it!

adamfrey16:03:42

@tomjack not yet. The one thing I’m observing is that querying a synthetic attribute like :board/percentage, which doesn’t exist anywhere in the app state, is going to clutter up my parser function significantly. Previously my read parser fn for :board/list is just (om/db->tree query (get st key) st), which is great and generic and works regardless of what the component query is, resolving joins and idents. But a naive approach to calculating :board/percentage there will lead to a mess of conditional logic, especially if I later need another aggregation attribute.

tomjack16:03:45

I was doing something similar, but for me it was just (defmethod read :board/percentage [env k] ...)

tomjack16:03:39

the method for :board/list didn't need to know about :board/percentage. not sure if I'm confused

tomjack16:03:59

one thing I had wondered about, though: if you do a mutation and specify just :todo/completed? in the reads, om will not know that your :board/percentage also needs to be read. whereas if you just query for all the todos and aggregate in render, it will

tomjack16:03:09

I think. again, likely confused simple_smile

tomjack16:03:36

(at the moment I am back to aggregating in render, because it is plenty fast enough for me..)

tomjack16:03:50

I guess I see why it's unclean for you. (om/db->tree query (get st key) st) is a read function fit for tutorials, but I never use anything like that simple_smile

adamfrey16:03:26

Splitting it out to a separate read function like you said is desirable to me. I’ll try something like that. I’m not averse to writing code, I’m just trying to think big simple_smile

tomjack16:03:48

I should probably stop talking. I currently have this for keys like :board/list

tomjack16:03:57

(defn read-many-ref [env k]
  (let [{:keys [state data query parser]} env
        st @state
        data (or data st)
        refs (get data k)]
    {:value (if (contains? data k)
              (into []
                (map (fn [ref]
                       (parser (assoc env :data (get-in st ref))
                         (if (map? query)
                           (query (ref 0))
                           query))))
                refs))}))

tomjack16:03:57

but I notice that e.g. untangled-web does something like what you have

adamfrey16:03:37

I haven’t looked at untangled source yet. I’ll check it out

tomjack16:03:00

was looking at untangled.client.impl.om-plumbing/read-local

tomjack16:03:40

the read functions which receive a query but do not recursively call the parser always confused me

tomjack16:03:06

I figured they were just tutorial simplifications simple_smile

tony.kay18:03:57

@tomjack: No need for recursion...`db->tree` does that for you

tony.kay18:03:21

Unless you need some kind of custom thing (e.g. parameter interpretation) there isn't much it won't do

anmonteiro18:03:36

@dnolen: I'm seeing expr->ast lose query-root metadata in joins

dnolen18:03:48

that’s possible

dnolen18:03:55

might have missed some case

anmonteiro18:03:00

willing to merge a PR that adds :query-root to the AST in join->ast?

anmonteiro18:03:14

that's where I've tracked it down to

anmonteiro18:03:04

whenever the join has query-root metadata, add it to the resulting ast map

anmonteiro18:03:18

@dnolen: issue needed or just PR?

dnolen18:03:28

PR is fine

dnolen18:03:00

also happy to cut a an Om release today with the latest fixes

anmonteiro18:03:36

I'll send you a PR in a few minutes, it'd be cool if this one was included as well

anmonteiro18:03:09

@dnolen: #655 fixes it

anmonteiro18:03:15

cool, thanks

tomjack18:03:40

@tony.kay: it won't use my parser, right?

tony.kay18:03:06

What is "it" in this context

tomjack18:03:38

I think maybe I understand. if your read function just uses db->tree, then using db->tree makes sense. but as soon as your read does anything different for some query stuff, then you will want to ensure that db->tree is not used with queries containing that stuff?

iwankaramazow18:03:10

@tomjack: indeed, you'll use om/db->tree whenever it works. However some cases (like parameterization), needs you to do more stuff manually

tomjack18:03:01

so when I write (defmethod read :board/list ...), I assume that I know nothing about the query. maybe the query contains parameterization or other weird stuff, maybe it doesn't, I dunno. so still not sure I'd ever use db->tree -- guess I'm probably still confused

tomjack18:03:39

if I have a whole app with no weird query stuff, then I can see using db->tree

tomjack19:03:31

I guess "there is no weird stuff in queries for these referenced entities" is something I could know

tomjack19:03:55

What're the advantages of db->tree over a 'general' recursively parsing solution? Speed, I wonder?

anmonteiro19:03:49

@dnolen: my problem wasn't solved with the join->ast patch, even though that was problematic too

anmonteiro19:03:24

I've narrowed it down to focused-join (which focus-query calls) losing the metadata

anmonteiro19:03:52

this happens in index-root and then full-query returns queries without metadata

anmonteiro19:03:14

working on a patch for this one

anmonteiro19:03:28

I've opened #656 to track this issue, as I'm not sure I'll finish the patch today

anmonteiro19:03:54

@dnolen: was actually a simple one, PR #657 fixes it (also tested in my project and the issue is now gone)

tony.kay21:03:23

@tomjack Personally, I avoid parameters on queries overall and use app state instead. It doesn't mesh perfectly with the remote story in the pure Om world, but it works for the UI, and in our apps we augment the server queries on transmission instead of in the UI.

tony.kay21:03:14

this eliminates the need for custom read parsing altogether. You end up doing a little bit of work elsewhere, but so far it has been a win

tony.kay21:03:33

For example, instead of using parameters to do pagination, we instead do pagination as a "view"...e.g. state in the app database that refers to the items to show. The UI query always just asks for the view. Then mutations can create that view as needed in reaction to events like "next page". Remote loading integrates very nicely with this, even when loading a page at a time.

tony.kay21:03:22

This is also the approach #C0PULSD25 takes

tony.kay21:03:07

All that said: I do see a real reason to write a more complex parser on the server. Parameters are pretty important there.

dnolen21:03:58

@anmonteiro: merged

seanirby21:03:34

i find myself using computed properties to communicate from children to parents, but using core async for communicating arbitrarily across the UI tree. Is that the right approach?

tony.kay22:03:35

@seanirby: Not in Om next

tony.kay22:03:07

The UI should be pure functions, the mutations abstract. Trigger all of the changes with a single mutation. The UI updates cross-tree use follow-on transaction reads

tony.kay22:03:36

no core async or app event systems needed (or desired) at the UI level

tony.kay22:03:42

(om/transact! this '[(app/f) :properties-to-trigger-renders])

tony.kay22:03:42

The "follow-on reads" are keywords that appear in UI queries. Om will re-render anything that queries the provided keywords, allowing you to do it via data dependency instead of UI structure.

seanirby22:03:00

tony.kay: the use case im talking about is like the one in your overview

seanirby22:03:22

the friend button communicating up to the friends widget

tony.kay22:03:26

communicating from child to parent is a callback, that then typically does a transact. The reason you use a parent for that is to make sure things like ownership re-rendering happen without needing follow-on reads

tony.kay22:03:36

where do I use async for that?

seanirby22:03:51

but you use computed properties right ?

tony.kay22:03:07

I just updated the untangled tutorial with a cross-tree exercise in the Mutation exercises

tony.kay22:03:35

So, I'd recommend playing with that, since it uses the follow-on reads I just described

tony.kay22:03:16

computed is about passing calculated things to children. callbacks being a primary example

tony.kay22:03:53

doing mutations in a parent is important when that parent is the owner of a collection of children (e.g. a list that needs to re-render because of entry/exit of a child)

tony.kay22:03:25

The follow-on reads are necessary when some part of the UI is unrelated, and just needs to re-render in response to an arbitrary mutation.

seanirby22:03:42

tony.kay: i appreciate the detailed response, I'll check out that tutorial.

adamkowalski22:03:29

is there any good way to see how your web app looks in both a browser and mobile device at the same time?

adamkowalski22:03:35

and have it automatically update with any change?

adamkowalski22:03:39

figwheel makes developing on the browser a breeze, but I would also like to see how things look on mobile safari/chrome. I currently have a port forwarded so I can view my site on mobile but there is no figwheel connection to it

seanirby22:03:49

adamkowalski: have you checked out the phone emulators in chrome?

adamkowalski22:03:03

yeah I have and they are nice, but for whatever reason it seems like I get subtle ui differences in real devices then whatever the emulators show me

adamkowalski22:03:28

especially on safari it seems like there is a different default css for certain things

adamkowalski22:03:51

like rounded corners randomly appear in my elements and I have to specify borderRadius: “none” lol

seanirby22:03:17

adamkowalski: yeah they're not perfect, but for me they suffice for initial devleopment

adamkowalski22:03:40

yeah, they are definitely still nice. thanks for the tip simple_smile

adamkowalski22:03:54

i just wish we had something like browsersync or something