# om

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

joshfrench 23:42:27

is the Thinking With Links tutorial out of date? the example code doesn’t seem to read [:current-user _] at all

dnolen 00:02:29

@joshfrench: issue already been reported

dnolen 00:02:33

will take a look later

tony.kay 00:55:19

@dnolen: db->tree seems ok with respect to [:k _] idents. Just ran (and even embellished) tests on tip of master

dnolen 00:55:38

@tony.kay: yeah I see we have tests for this

dnolen 00:55:43

putting the tutorial into a devcard now

dnolen 01:00:10

@joshfrench: I copied and pasted the tutorial into master - works fine

jethroksy 04:16:12

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

dvcrn 10:17: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?)

hmadelaine 11:30: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.

anmonteiro 13:27:07

@jethroksy: thx, fixed

anmonteiro 13:29:45

@dvcrn: though I'm only integrating 1 or 2 routes, I have a sample project integrating with a REST API here:

anmonteiro 13:30:05

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

anmonteiro 13:30:20

so it's good for comparing

nxqd 13:58:11

hi guys, what is the proper request to get todo item by-id like the one I highlighted in the source code

nblumoe 14:07: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.

nblumoe 14:08:46

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

nblumoe 14:12:48

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

nblumoe 14:14:04

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

anmonteiro 14:15:57

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

nblumoe 14:16:38

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

anmonteiro 14:17:31

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

anmonteiro 14:17:59

the default approach is quite naïve

anmonteiro 14:18:22

so feel free to adapt it to your use case

nblumoe 14:19:31

is there some documentation you could refer to? Or should I try to make sense from the code around ?

anmonteiro 14:20:47

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

anmonteiro 14:21:40

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

nblumoe 14:24:24

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

nblumoe 14:24:26


nblumoe 14:26:41

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

anmonteiro 14:31:39

not sure about merge and merge-idents, sorry

danielstockton 14:37:26

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

danielstockton 14:38:39

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

danielstockton 14:39:42

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

nblumoe 14:44:04

fair enough, thanks

nblumoe 14:44:17

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

danielstockton 14:51:20

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

danielstockton 14:51:40

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

nblumoe 15:27:04

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

joshfrench 18:09: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?

jannis 18:34: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.

joshfrench 20:08:51

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

jannis 20:10: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.

jannis 20:11:05

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

joshfrench 20:13:29

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

joshfrench 20:13:43

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

joshfrench 20:14: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

jannis 20:17: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.

jannis 20:18: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:

dnolen 20:22:15

no opinions about hard problems

dnolen 20:22:24

you need to sort that our yourself

dnolen 20:22:28

Om Next is not a concurrency library

joshfrench 20:27:53

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

joshfrench 20:29: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

dnolen 20:32:06

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

joshfrench 20:39:14


vipaca 21:46:55

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

dnolen 21:48:59

@vipaca: possibly lots of reasons

vipaca 21:48:59

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

dnolen 21:49:14

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

dnolen 21:49:20

aka know exactly how Om Next works

vipaca 21:49:36

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

dnolen 21:49:59

anyways not enough information and a lot of statements

dnolen 21:50:06

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

vipaca 21:50:27

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

vipaca 21:51:20

Not even completely sure that the atom is being reset!

dnolen 21:51:40

then I would slow down and possibly start over

dnolen 21:51:58

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

dnolen 21:52:08

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

vipaca 21:52:41

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

dnolen 21:53:00

heh then yes I would use something else :simple_smile:

vipaca 21:53:51

perhaps :simple_smile:

vipaca 22:22:59

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

tony.kay 22:23: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.

smeister 22:29:02

process-roots keeps loosing my query parameters

smeister 22:29:12

if i remove the merge-joins step it works

tony.kay 22:30:22

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

smeister 22:30:26

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

tony.kay 22:31:19

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

smeister 22:31:28

and the join is a query root

tony.kay 22:31:32

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

smeister 22:32:21

thats everything

smeister 22:32:35

i also don

smeister 22:33:23

't understand why merge joins seemingly ignores parameters

tony.kay 22:35:15

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

smeister 22:38:33

sorry copied the wrong line to the gist

vipaca 22:55:06

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

dnolen 22:55:47

@vipaca: this question doesn’t make sense

dnolen 22:55:56

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

vipaca 22:57:04

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

tony.kay 22:57:37

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

vipaca 22:58: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.