Clojurians
#om
<
2015-12-17
>

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

jethroksy02:12:12

@anmonteiro: it seems the generated lein template with option +next doesn't include deps for either om or om.next in project.clj

dvcrn08:12:19

are there any good ressources in how to integrate om with a existing REST API? (or in general stuff that doesn't use fragments?)

hmadelaine09:12:45

Hi @joshfrench, @dnolen just to confirm that it works fine with master. I think my problem came from the lein install of Om. I have cleaned manually om/target and resources/public/devcards/out. Sorry for the false alarm.

anmonteiro11:12:07

@jethroksy: thx, fixed

anmonteiro11:12:45

@dvcrn: though I'm only integrating 1 or 2 routes, I have a sample project integrating with a REST API here: https://github.com/anmonteiro/deathrow

anmonteiro11:12:05

it has Om & Om Next code, providing the same functionality

anmonteiro11:12:20

so it's good for comparing

nxqd11:12:11

hi guys, what is the proper request to get todo item by-id like the one I highlighted in the source code https://github.com/swannodette/om-next-demo/blob/master/todomvc/src/clj/todomvc/server.clj#L99-L103

nblumoe12:12:34

How would I incorporate novelty received from a REST endpoint into the application state? I am passing the novel data to the Om.Next callback once I got the server response. How do I get the data in correct shape? I have a root query with accounts/list and subqueries for attributes of accounts. From the REST AJAX call, I would like to update a single attribute. Accounts have an Ident on db/id, which would also be in the scope of building the novelty structure.

nblumoe12:12:46

I should also mention, that the AJAX call simply gets triggered via om/transact -> parser/send if that is not obvious

nblumoe12:12:48

one step further:

(callback  {:accounts/by-id {(get-in account [:params :db/id])
                                                            {:name "FOOOOO"}}})

nblumoe12:12:04

However, I want this to be a merge, not a replacement of the whole account

anmonteiro12:12:57

@nblumoe: probably need to override :merge-tree in the reconciler to suit your behavior

nblumoe12:12:38

But am I on the right track with this? Swapping this into the application state myself should be avoided, right?

anmonteiro12:12:31

I think the behavior should be defined in :merge-tree

anmonteiro12:12:59

the default approach is quite naïve

anmonteiro12:12:22

so feel free to adapt it to your use case

nblumoe12:12:31

is there some documentation you could refer to? Or should I try to make sense from the code around https://github.com/omcljs/om/blob/b61fa371e5ec81f54addcbd7e6e0c4655bfbebc0/src/main/om/next.cljs#L1329 ?

anmonteiro12:12:47

@nblumoe: I think there's no docs on this yet

anmonteiro12:12:40

it's what's called on merge-novelty right at the end

nblumoe12:12:24

ok thanks will try to make some more sense out of this

nblumoe12:12:41

Would you mind giving a short description of merge merge-ident and merge-tree? What is supposed to do what?

anmonteiro12:12:39

not sure about merge and merge-idents, sorry

danielstockton12:12:26

@nblumoe merge just runs merge-tree, migrate and merge-idents (lower level)

danielstockton12:12:39

merge-tree is for updating the state, migrate is for updating tempids and merge-idents for adding...idents :simple_smile:

danielstockton12:12:42

the source isn't too hard to understand for the default implementations

nblumoe12:12:04

fair enough, thanks

nblumoe12:12:17

I was wondering though about the Design and the implications of changing that.

danielstockton12:12:20

using datascript, you have to implement merge-tree and migrate at least

danielstockton12:12:40

depends on your store but they're designed to be pluggable

nblumoe13:12:04

@anmonteiro: @danielstockton thanks, managed to get it done! :thumbsup:

joshfrench16:12:42

if i'm persisting an entity remotely: (create! {:db/id temp-id}) sometimes i'd like to also re-read the new entity, in case the remote has changed or added some attribute: (:read {:db/id temp-id}). it seems impossible to do this in one shot, since there's no way to resolve the temp-id from :read against the result of create! within the remote parser. right now my workaround is to pass a static identifier: [(create! {:client-id (str temp-id)}) (:read {:client-id (str temp-id)})]. but that feels redundant and also requires that those transactions run in the same sequence on the remote(s), which i'm not sure is a safe assumption. am i overlooking a better way to do this?

jannis16:12:09

@joshfrench: Hmm, if this doesn't already work perhaps we can make Om read keys aware of tempid migration somehow, so you could ask to re-read the tempid and Om would internally perform tempid migration and re-read the real thing.

joshfrench18:12:51

@jannis seems like you’d run into problems if you had multiple db transactions — how would you know which result to resolve against?

jannis18:12:09

@joshfrench: True. Although... if they are part of the same query (multiple transactions + reads) it would know, even if only one of the transaction results in the combined result has a tempid mapping.

jannis18:12:05

If the transactions are sent as separate queries... yeah, I can see how that would be a problem.

joshfrench18:12:29

i’m imagining a scenario like [(transact-A! {...}) (transact-B! {...}) (:read temp-id)] where you’d have two possible results/tempid maps

joshfrench18:12:43

i suppose you could just try each result until you find one that can resolve your ID

joshfrench18:12:44

but it seems like there’s still a timing issue — even if i knew which txn to resolve against, i still need to run it and have the results prior to executing :read so i know what ID i’m actually reading

jannis18:12:30

@joshfrench: I haven't looked at the code in a while but my guess would be that Om already consolidates tempid maps into one before the migration. But I'm not sure.

jannis18:12:56

Regarding the timing issue... perhaps both client and server-side parser could translate tempid reads on the fly while processing the query? Not sure that's feasible. I'm sure David will have a more informed opinion on all this. :simple_smile:

dnolen18:12:15

no opinions about hard problems

dnolen18:12:24

you need to sort that our yourself

dnolen18:12:28

Om Next is not a concurrency library

joshfrench18:12:53

is it safe to assume that within a vector of transactions, the sequence will be preserved on the remote(s)?

joshfrench18:12:08

if order were fixed, i could use a request-level map to let earlier transactions add ID translations for later transactions to refer to

dnolen18:12:06

it’s a good thing query roots are ordered vectors no?

joshfrench18:12:14

:simple_smile:

vipaca19:12:55

Any reasons why consecutive resets on an atom state might be ignored by om component listeners?

dnolen19:12:59

@vipaca: possibly lots of reasons

vipaca19:12:59

It seems that even when the atom's state changes the UI is not updated immediately.

dnolen19:12:14

if you’re using reset! you should be OK with knowing exactly what you are doing

dnolen19:12:20

aka know exactly how Om Next works

vipaca19:12:36

And slowing down state changes has not worked e.g. sleep

dnolen19:12:59

anyways not enough information and a lot of statements

dnolen19:12:06

make a minimal case of the problem and someone will look at it

vipaca19:12:27

I'm kinda lost and don't know anything about Om or Next.

vipaca19:12:20

Not even completely sure that the atom is being reset!

dnolen19:12:40

then I would slow down and possibly start over

dnolen19:12:58

stick with the tutorials and modifying them - then ask questions when things don’t match your expectations

dnolen19:12:08

otherwise nobody will have any clue why something isn’t working for you

vipaca19:12:41

solid advice that I just can't take for this project/problem.

dnolen19:12:00

heh then yes I would use something else :simple_smile:

vipaca19:12:51

perhaps :simple_smile:

vipaca20:12:59

I think what I might be missing is that my event handler is blocking om from rendering component upon atom state change.

tony.kay20:12:41

@joshfrench: One note on ordering: If you use process-roots, it is possible for the reads to be re-ordered (due to root promotion merging)...but the order of the mutations is preserved.

smeister20:12:02

process-roots keeps loosing my query parameters

smeister20:12:12

if i remove the merge-joins step it works

tony.kay20:12:22

@smeister: can you post a gist that shows the problem?

smeister20:12:26

({:auth [...more stuff]} {:user/email test, :user/password s}) becomes {:auth [...more stuff]}

tony.kay20:12:19

that exact kind of test case works for me in general. Might need a bit more specific

smeister20:12:28

and the join is a query root

tony.kay20:12:32

what is the context? Is there more than one of those being promoted to a root?

smeister20:12:21

thats everything

smeister20:12:23

't understand why merge joins seemingly ignores parameters

tony.kay20:12:15

ok, let me look...I'm in two convos...so might take a few

smeister20:12:33

sorry copied the wrong line to the gist

vipaca20:12:06

Can om deserialize arbitrary object in a component's state?

dnolen20:12:47

@vipaca: this question doesn’t make sense

dnolen20:12:56

Om doesn’t have anything to do with serialization at all

vipaca20:12:04

oh ok, well when I store clojure data structure in javascript objects I thought there was a serialization going on in there.

tony.kay20:12:37

@smeister: I'm not able to reproduce your output via a test, using your exact reported query, query root, and process-roots.

vipaca20:12:36

I thought I saw that when I added an entity from datascript to a map in om component's state atom, and then read it during another event it was no longer a datascript entity.

vipaca21:12:18

dnolen: Would you expect arbitrary object stored in component state across events and the reaccessed in another event to be consistent(still and arbitrary object)?

dnolen21:12:31

@vipaca: sorry I do not know what you are asking me

dnolen21:12:40

a minimal code sample of what you are talking about would help a lot

vipaca21:12:58

After testing in the repl with figwheel it seems okay, but this not across events in browser. However it does seem to be working across events.

tony.kay21:12:31

@smeister: OK, Able to reproduce your issue now. A bit puzzled as to why the original test was passing.

tony.kay21:12:45

I'm thinking the comments from @dnolen about leveraging the AST might be in order here...might simplify this algorithm and fix this problem at the same time.

tony.kay21:12:00

I'll open an issue and try to get some time to work on it

vipaca21:12:09

So is this a hard rule "state should only consist of associative data structures like maps and vectors" or can any object be used for state?

adammiller22:12:27

@vipaca: what are you thinking? All that makes sense is associative structures (i.e. it has to have meaning and be able to be queried)

vipaca22:12:11

Can an arbitrary object that stores state be used e.g. records, structs, pojo that has accessor for example?

adammiller22:12:52

but to answer your question, state is managed via atom and the only things you can hold in atom is one of clojures immutable data structures

vipaca22:12:09

More importantly can arbitrary values be stored in state?

vipaca22:12:37

But can the values stored in the atom can be user defined?

vipaca22:12:34

I do apologize for all the n00b questions today.

adammiller22:12:52

we are all n00b’s at something! are we talking about state with om.next or are you just asking about atoms in general?

adammiller22:12:50

I’d say if you are comfortable with clojure/clojurescript but new to react based frameworks that you may want to check out reagent. A little easier to jump into and grasp than Om/Om.next IMO. Jumping straight into Om without much cljs experience is tough.

anisoptera22:12:29

oh that's a good suggestion, i should check that out

anisoptera22:12:52

i was having issues just using om

anisoptera22:12:00

trying to learn too many things at once :simple_smile:

adammiller22:12:44

also a library called re-frame you can use with reagent…I think their readme on the github project is very well done and enlightening no matter which route you end up going: https://github.com/Day8/re-frame

dnolen22:12:11

@vipaca you can store arbitrary values but only maps and vectors can be understood by the query bits. arbitrary values will not be traversed for links for example.

vipaca22:12:21

btw, I reimplemented my approach to allow return after each state change and then trigger a subsequent event trigger and it now it renders each state changes upon event completion.

vipaca22:12:53

I was under the misunderstanding that I simply needed to update the atom and then render would occur asynchronously in om component.

vipaca22:12:23

When I began the implementation I was not in a very javascript like state of mind.

vipaca22:12:41

e.g. writing blocking code and expecting om components to still handle events.

vipaca22:12:26

adammiller: thanks for the reagent advice its the second time today Ive seen the reference.

tony.kay23:12:50

@dnolen: This may be one you don't care about, because it relates to side-band pre-loading of data; however, here is a problem that we're having to work around: The merge! functionality of Om on incoming joins keyed by idents uses the indexer to find the queries in order to normalize the value. That makes sense, since the ident keys are for data that associates with disparate components. However, if those components are not yet on screen (in the current UI query) then normalization fails because they are not in the indexer. Might be nice to at least have a way to pass a list of component classes so that you could help it out...like we can now pass a query to help with normalization of tree responses.

dnolen23:12:56

@tony.kay: will need to think about it, but yes I understand the problem and I agree we need something

tony.kay23:12:37

ok...playing with it, looks like just passing the query might work for remoting...since you derive the components in question from the query

tony.kay23:12:43

so that would be consistent without api change

tony.kay23:12:10

then don't need the indexer at all

tony.kay23:12:15

(at least for that code path)