Fork me on GitHub
#om
<
2015-12-08
>
tomc02:12:45

Thanks, I'll update the gist and post it here tomorrow.

Chris O’Donnell03:12:13

I'm struggling a bit with tony kay's om-tutorial. I'm trying to do the UI Queries and State Exercises, and I'm struggling to get my Person component's props to be what I want. When I do (om/props this), I get an entity [:db/id 1] rather than a map with the attributes I want. If someone could give me an idea of how to resolve the entity into the map I want (with :person/name, :person/mate, etc.), I would much appreciate it.

noonian05:12:14

What you get will be the :value returned but your parsers read function. If you are using links in your parser you will need to use Om’s db->tree helper to recursively follow links and build up the data.

thomasdeutsch08:12:55

given a map :person/by-id {"1" {:name "Tom"} "2" {:name "Jon"}} and a list with links: :person-list [[:person/by-id "1"] [:person/by-id "2"]] when i delete one of the persons, the link in my list becomes invalid (nil). In the same transaction, i can search for all links and delete them manually - is this how it should be done?

txus08:12:51

mfikes’ auto-completion code is beautiful. Can’t believe that’s running on iOS and it’s barely 100 lines of lisp

txus08:12:25

100 lines is the length of a freaking empty ViewController template in Swift lol

artemyarulin08:12:00

om-next really shines on mobile

txus09:12:38

my co-founders are really excited about React / React Native, and I try to sell them om.next for both web & mobile apps but the lisp argument is not enough for them, and I don’t think I fully grasp all the potential of om.next good enough to sell it. What are the main strengths would you say?

artemyarulin09:12:42

because of single app state and idents it will scale when your UI grows. It scales from the side of backend communication. It scales from the side of your custom requirements (server push, custom app state db, etc)

txus09:12:16

doesn’t redux try a similar approach to state management?

artemyarulin09:12:46

not that familiar with it to compare

txus09:12:02

me neither, they just mentioned it heh

danielstockton09:12:17

scalability isn't a main strength, i would say

danielstockton09:12:22

lots of systems scale in different ways

danielstockton09:12:45

it's really an improvement over REST, you have to have experienced the problems with REST apis to really see the benefits

danielstockton09:12:16

the lisp argument is orthogonal to om.next, its more an argument for clojurescript

danielstockton09:12:38

but it shows where the good ideas are coming from, there is nothing much like om.next at the moment

artemyarulin09:12:29

well technically you can achieve about the same if you take redux + relay + graphQL + immutablejs

artemyarulin09:12:10

although I think om-next + CLJS solves problems better

danielstockton09:12:54

there would be a lot to reimplement in making those all work together in a comparible system

danielstockton09:12:00

you'd probably end up with much more code to maintain

danielstockton09:12:11

definitely in fact

artemyarulin09:12:18

and the end result would be still not that good, yep

artemyarulin09:12:37

so om-next is the best thing in the world, what else we need to say? simple_smile

danielstockton09:12:59

another strength is completely decoupling the ui from state

danielstockton09:12:06

and the state model

danielstockton09:12:21

through queries

danielstockton09:12:33

so you can change your mind to using datascript instead of atoms, or some other system

danielstockton09:12:42

and not have to change any of your compenents

danielstockton09:12:50

just the parser

danielstockton09:12:35

@txus you mentioned web and mobile apps (plural)

danielstockton09:12:50

om.next can really shine when you have multiple clients using the same api

danielstockton09:12:57

your api will be much cleaner

txus09:12:48

those are some compelling arguments simple_smile

txus09:12:26

over Christmas I’ll spend some time with them in Barcelona and I plan on having a bit of a workshop on om.next + react.native, something flashy to spark their interest

artemyarulin09:12:14

Show them figwheel + repl and they will buy it the same moment

txus09:12:11

they already like Clojure from a distance, the workflow and all the jazz, it’s really impressive

txus09:12:01

but they’re afraid on taking on too much by learning React and cljs, and they’re afraid of the stability of both things combined / om lagging behind or being eventually incompatible with react, etc

txus09:12:04

mostly FUD

danielstockton09:12:42

As I understand it, om.next is largely decoupled from react.dom and in the future using another virtual dom implementation may be possible

danielstockton09:12:08

That said, it is still alpha and I understand it being a hard-sell for some people at this stage

txus09:12:54

I know simple_smile let’s see if some demo / workshop works for them

bmaddy09:12:03

Is anyone else having trouble with the "Change the Query!" section of the om.next quick start? https://github.com/omcljs/om/wiki/Quick-Start-%28om.next%29#change-the-query om.set-query! changes things in a way I wouldn't expect:

cljs.user=> (in-ns 'om-tutorial.core)
nil
om-tutorial.core=> (om/get-query (om/class->any reconciler AnimalsList))
[:app/title (:animals/list {:start 0, :end 10})]
om-tutorial.core=> (om/set-query! (om/class->any reconciler AnimalsList) {:params {:start 0 :end 5}})
nil
om-tutorial.core=> (om/get-query (om/class->any reconciler AnimalsList))
{:params {:start 0, :end 5}}
I would expect get-query there to return [:app/title (:animals/list {:start 0, :end 5})]. Is anyone else seeing this?

griffio10:12:29

@bmaddy: Just to confirm, I do see [:app/title (:animals/list {:start 0, :end 5})] ,on Alpha24/25.

bmaddy10:12:18

Weird, there must be something wrong on my end then. I'll try copying in the code again. Thanks @griffilo.

griffio10:12:18

@bmaddy yup, check version, clean build etc. It definitely works as to your expectation!

bmaddy10:12:26

Do you by chance know how to clean it when running like this? lein run -m clojure.main script/figwheel.clj lein cljsbuild clean doesn't seem to work since cljsbuild isn't in the project.clj.

bmaddy10:12:20

Heh, I found it on your github repo. simple_smile

griffio10:12:25

@bmaddy: You can just do (clean-builds) in the repl - otherwise you will have to setup lein-build

bmaddy10:12:42

(clean-builds) fixed everything up for me--Thanks @griffio!

txus15:12:19

I’m not sure I understand what this error message means: No queries exist for component path (ui.core/RootView ui.poi/PoiView)

txus15:12:31

I’ve gotten similar errors and fixed them somehow but I always forget how

txus15:12:38

what does it mean exactly?

txus15:12:15

hmm yeah, I think I’m doing something like that. But I don’t quite get how else I could do it

txus15:12:23

having subcomponents with subqueries

txus15:12:49

is there any code in the wild with deeply nested components / queries? that’d be really cool to study

anmonteiro15:12:57

I'll have a look if you share your components' queries

tomc15:12:58

@txus I'm still looking at the same thing. Mind posting back here if you get a solution? I'll post my gist once I get it updated and we can compare notes.

txus15:12:19

@anmonteiro: PoiView is a component rendered by RootView

anmonteiro15:12:12

you're stealing PoiView's query

txus15:12:45

oh I thought that was expected? The root query needs to be a complete tree of everything everyone needs no?

anmonteiro15:12:53

yes, but not like this

anmonteiro15:12:58

give me a second

anmonteiro15:12:42

there, hope it helps

txus15:12:43

ah!! mann of course read is mine and it can read custom join names! I’ve always been afraid of using names that don’t specifically mimic the shape of the initial data map

txus15:12:48

@anmonteiro: thanks so much!

txus15:12:56

it makes a lot of sense now

anmonteiro15:12:20

exactly, env in the parser gives you that degree of freedom

anmonteiro15:12:30

happy to help

dnolen15:12:00

@txus hopefully drives the point home yet again, that it’s completely up to you what Om Next does and how it does it 😉

txus15:12:07

this is the ‘click’ that I was missing in om.next simple_smile

tomc15:12:23

I'm not understanding why the original way was wrong. The 'stolen' query was still a grammatically correct query, no?

dnolen15:12:41

@tomc yes but it cannot work

dnolen15:12:51

I’ve already pinned stuff like this to the channel … but

dnolen15:12:04

Om Next doesn’t have syntax so we can’t control user errors like this

dnolen15:12:20

people assume they can freely build up queries however they like - but of course that isn’t true

dnolen15:12:32

Query <-> Component is a one to one thing

dnolen15:12:59

you cannot steal queries

dnolen15:12:24

if you think about it a little more it’s obvious doing so is a modularity fubar

dnolen15:12:37

you just took an opaque thing somebody needs and messed it up

tomc15:12:03

Yeah that actually answers a question I hadn't really formulated well. When doing it my broken way I ended up passing everything from RootView's props into the child component, which is obviously bad. Thanks for the help.

dnolen15:12:31

@tomc: be sure not to conflate issues here

dnolen15:12:39

of course the root component is going to get everything

dnolen15:12:00

but it should just pass on the keys that children need as expressed in the query and not muck it up

txus15:12:13

I feel so dumb! that’s really the point of decoupling components from the shape of the tree

dnolen15:12:25

transformation of data in components is a BIG nono

dnolen15:12:37

the whole point of having a declarative query is - GET IT RIGHT

dnolen15:12:41

render, done

txus15:12:54

so nice!!

dnolen15:12:39

it’s in this sense that Om Next is decomplected

dnolen15:12:53

all the data manipulation stuff happens in parse, or in send

dnolen15:12:16

components are just about rendering, life cycle, animation, and host events

dnolen15:12:00

with the tiny, tiny bit of loop back permitted by transact! to transition the app to the next logical state

tomc15:12:38

The gist I posted now shows a working version of the Components, Identity, and Normalization tutorial with routing, in case that's useful to anyone: https://gist.github.com/tomconnors/c1cceaae84fd059e37a3

txus15:12:29

@dnolen: I don’t quite get the “read hints” on mutations. They seem to have no effect?

txus15:12:54

{:value {:keys [:foo :bar]} :action #(…)}

dnolen15:12:48

@txus yes no effect

dnolen15:12:02

it’s just to communicate the set of things you can read

dnolen15:12:00

in a world with diverse clients you don’t want clients to re-read stuff they cannot display

dnolen15:12:19

maybe a desktop client is show 4 different views and can accommodate those keys, but iOS client can only show 1

dnolen15:12:25

so imposing the same reads on everything is just backtracking on the problem Om Next wants to solve

noonian16:12:06

@dnolen: I think there is a bug in process-roots where it doesn’t re-create a union correctly (doesn’t convert vector of map entries into a map).

noonian16:12:48

I’m not using :query-root yet, so my re-written query should be the same

noonian16:12:38

for this query:

[{:app/pages
  {:page/home
   [{:user/rooms [:id :roomname]} {:app/rooms [:id :roomname]}]}}]
(:query (om/process-roots the-above-query)) returns
[{:app/pages
  [[:page/home
    [{:user/rooms [:id :roomname]} {:app/rooms [:id :roomname]}]]]}]

dnolen16:12:08

@noonian: thanks for the report, file a bug with this information, thanks

noonian16:12:29

Cool, I’ll open an issue.

maackle20:12:32

Can anyone tell me if it’s constructive at this point to submit issues/PRs on om.next documentation, or is that too nit-picky? Maybe it’s all going to be re-written soon. For instance, I found the doc for om.next/update-state! misleading

dnolen20:12:20

@maackle: you should always ask first here for clarification

dnolen20:12:28

and no PRs or issues for docs

maackle20:12:27

I figured it out, but I think the statement “Similar to Clojure(Script)’s update-in” is incorrect (https://github.com/omcljs/om/wiki/Documentation-(om.next)#update-state)

maackle20:12:40

namely it doesn’t seem to work with korks before the update function

noonian20:12:42

changing to “Similar to Clojure(Script)’s uptate” would probably make sense, since it doesn’t take a vector of keys like the *-in family of functions

anmonteiro20:12:23

it can take a vector of keys

maackle20:12:40

I had no luck getting it to take a key or a vector of keys

noonian20:12:51

I’m looking at the source and it definitely doesn’t heh

anmonteiro20:12:52

(om.next/update-state! some-component update-in [:some/key :other/key] inc)

noonian20:12:04

that vector of keys is an argument to update-in

maackle20:12:27

I would expect (om/update-state! some-component [:foo :bar] (fn [] …)) to work

maackle20:12:42

from the docs

anmonteiro20:12:58

ah I get your confusion now

dnolen20:12:26

it should be fixed to say update

maackle20:12:31

but yeah, using update/`update-in` makes that functionality pretty unnecessary

anmonteiro20:12:50

@dnolen: I don't think it's even similar to update

anmonteiro20:12:58

more like swap!

noonian20:12:16

yeah, you’re right

dnolen20:12:35

ah heh, right

dnolen20:12:36

yeah should just fix update-state! to actually take k-or-ks like it did before

dnolen20:12:49

patch welcome, it’s quite trivial

anmonteiro20:12:58

I have the time to do it

anmonteiro20:12:04

was going to ask if you'd take the patch

anmonteiro20:12:15

if nobody else wants to tackle that

dnolen20:12:47

hrm actually

noonian20:12:54

how do you run the tests for om btw?

dnolen20:12:59

I think that’s probably a bit awkard

dnolen20:12:09

may be we should just say it’s like swap!

dnolen20:12:04

@anmonteiro: yeah I think we should ^

dnolen20:12:14

we don’t actually have anything like update-in anywhere else

noonian20:12:30

@dnolen: get-state can work like get-in

anmonteiro20:12:46

maybe @maackle was confused because that's how it used to work in om.core

noonian20:12:46

thats the only thing that might make someone expect it I think

noonian20:12:16

and the existing documentation heh

dnolen20:12:17

@noonian: but it really is just awkard

dnolen20:12:27

since the first argument is not a free thing like update-in

maackle20:12:34

@anmonteiro: I’m not that familiar with om at all, it was just that statement in the docs about update-in

dnolen20:12:50

even get-state is not like get-in due to k-or-ks

dnolen20:12:18

and pairing update-state! with update-in is simple enough

noonian20:12:36

yeah, I’m fine with having it like swap!

noonian20:12:43

we should definitely update the docs though

noonian20:12:57

I like how get-state works now btw 😛

dnolen20:12:35

I prefer the atom analogy for component local state

anmonteiro20:12:48

only submitting a patch for the docstring if David really wants or has more things to do

anmonteiro20:12:19

since it's only changing one line

dnolen20:12:32

I can fix the docstring here

dnolen20:12:43

anyone can feel free to fix up the wiki

anmonteiro20:12:48

that's what I thought 😛

dnolen20:12:24

docstring fixed

anmonteiro20:12:54

updating the wiki

Chris O’Donnell21:12:50

Is there some nice way of avoiding clojurescript throwing namespaces onto syntax-quoted code? I want \[(add-person {:name ~(om/get-state this :text)})]` to evaluate to [(add-person {:name "foo"})] rather than [(om-recipes.core/add-person {:name "foo"})].

Chris O’Donnell21:12:50

That \ is supposed to be a backtick.

thosmos21:12:01

@codonnell: FYI you can go back and edit your previous messages

Chris O’Donnell21:12:22

Thanks; I did not know that.

noonian21:12:27

there isn’t a nice way, but you can do [(~‘add-person …)]

noonian21:12:54

or, just use something like app/add-person so its already namespaced and then syntax quote will leave it alone

Chris O’Donnell21:12:34

@noonian: Thanks! That clears things up.

bplatz21:12:03

Is it recommended to use :merge with datascript? It seems it can be accomplished via :merge-tree by returning the dereferenced connection... but it seems the connection itself is what should be passed back in.

dnolen21:12:56

@bplatz: it’s not a problem if that’s what you mean

dnolen21:12:25

if there’s some issue that you see then express that - I haven’t heard a ton of feedback from DataScript users on :merge or :merge-tree

dnolen21:12:31

other than they’ve gotten it to work

bplatz21:12:16

I was trying to think through the mechanics. If you pass the de-ref'd DB, then I guess om will reset! the original atom with it? If so I suppose everything would still be in sync.

bplatz21:12:29

My concern was doing it that way the original DB conn might be out of sync, but I suppose because the datascript DB is a standard atom it should work.

marcol22:12:39

@bmaddy Thank you! With regards to posting the weird behavior of set-query! just got the same thing, and after a clean everything works!

tony.kay23:12:11

@dnolen: I've got time tonight to look at process-roots. I also talked to @jannis and it seems like he's discovered a bug in db->tree around joins combined with recursive queries. I'll look at that as well unless you're already working on either of these.

dnolen23:12:31

@tony.kay: yeah the behavior of process-roots is definitely wrong wrt. to joins and it seems like the tests around it are not actually testing what they should be at the moment

tony.kay23:12:56

I just saw the union issue...you're seeing others?

dnolen23:12:30

other issues just in the sense that the test on around line 1250 isn’t right

dnolen23:12:50

I should have read more closely but you cannot the union? predicate like htat

tony.kay23:12:12

the test on 1250???

tony.kay23:12:55

you mean the impl at 1250

tony.kay23:12:45

I had to do that because join? is mis-identifying unions AS joins

dnolen23:12:45

actually the problem is that union? is just wrong

tony.kay23:12:04

e.g. returning true on unions

dnolen23:12:23

no it’s just completely wrong

dnolen23:12:40

a union is map with one entry whose value part is a map

tony.kay23:12:42

if you could point to what behavior is wrong in the tests, that would help

dnolen23:12:51

but that’s not what union? tests

tony.kay23:12:06

I see what you mean

tony.kay23:12:30

but the code is : its a map and has more than one k-v pair

tony.kay23:12:35

that is syntactically a union

tony.kay23:12:59

we're talking about 2 things

tony.kay23:12:45

So, you're saying that a union has to be inside of a join

dnolen23:12:21

it can never appear on it’s own

dnolen23:12:32

the AST already reflects that

dnolen23:12:48

but the fact that the union? predicate is wrong has rippling effects

tony.kay23:12:54

Oh, so I bet I mis-wrote a test

tony.kay23:12:00

and then wrote the impl to that test

dnolen23:12:25

yeah I need to poke around at this since a bunch of tests fail if I fix union?

tony.kay23:12:07

OK, I can tell you that in this algorithm I was using that function to deal with the following ambiguity:

tony.kay23:12:29

{:j {:uk1 [] :uk2 []} vs. {:j {:j2 [sel]}

tony.kay23:12:42

one more deep

tony.kay23:12:23

so, when you see the latter, it COULD be a join, or it could be a map for a union

tony.kay23:12:49

since join? returns true on both (internal things), it can cause problems

dnolen23:12:39

so this stuff just needs to be cleaned up

dnolen23:12:08

but there’s another thing that concerns me somewhat with respect to process-roots

dnolen23:12:13

in that it actually doesn’t really handle traversal into unions - trying to think whether this is a problem in practice or not

tony.kay23:12:03

My take was that unions should not be traversed

tony.kay23:12:30

you are processing a query outside of the context of data

tony.kay23:12:41

so how could you chose the right path?

tony.kay23:12:02

I guess you could evaluate all possible paths, if you find no roots there is nothing to do

tony.kay23:12:11

pass it through without mods

tony.kay23:12:48

otherwise pass the first sub-branch that has a root to top...I guess you could technically promote any branch to the top

tony.kay23:12:05

if it is marked

tony.kay23:12:04

but then the result would need to be evaluated with ident somehow to figure out how to reassemble the prefix

noonian23:12:01

when using unions to achieve routing, you run into exactly the problem that it seems like process-roots is intended to solve

tony.kay23:12:37

@noonian: process-roots is about not sending UI-local path prefixes to a server

tony.kay23:12:50

nothing to do with routing

tony.kay23:12:57

(of the HTML5 sense)

noonian23:12:43

correct, and if you are using a union to achieve client side routing, then that union query (and outer join) is really just client machinery as well and you don’t want to send that to the server

tony.kay23:12:05

ah, I see your point

dnolen23:12:23

@tony.kay: yeah union queries are a natural way to describe choice

dnolen23:12:55

that said no I don’t think that process roots will ever need to deal with all choices

dnolen23:12:25

I think in general nested union queries will be layered into some kind of “focus"

noonian23:12:51

Yeah, and for the routing case your parser will theoretically only ever return a remote query for one of the union branches at a time.

dnolen23:12:59

so I don’t think making process-roots understand them will be particularly challenging

dnolen23:12:13

it’s just another thing to track (we already do this everywhere else)

tony.kay23:12:16

right, so all we need to do is traverse the query to the marked root and promote it

dnolen23:12:24

first things first let me try to fix the union? predicate and its uses

dnolen23:12:31

since that’s at the bottom

tony.kay23:12:54

ok. Be glad to lend a hand in a couple of hours. Let me know