Fork me on GitHub
#untangled
<
2016-04-20
>
cjmurphy00:04:19

There exists a 'binding' from your 'db' to your components that encompasses the whole thing.

ethangracer00:04:41

@amashi: we’re working on docs but quite honestly don’t have the time for a longer explanation right now. the talks are the best source of info, right now that’s the only place we have the overarching info

amashi00:04:04

OK, I will watch them. Thanks.

anmonteiro00:04:18

@amashi: to simply put my understanding of what Om Next buys you: You shift the control of the system to your clients. They bind to the “cloud” (whatever that means in your system — either a monolithic server or a group of microservices, or a combination of both) in a way that lets clients: 1. request the precise total response they need in their UI (without needing to reshape it in the client as you’d otherwise need, and without the burden of receiving too much or too little attributes in the server response) 2. atomically commit trees of data to the server (which are things you can easily do with things like Firebase, Meteor.JS, etc. but terribly hard to do with a RESTful backend) without actually having to sacrifice your precious relational database on the server (major improvement over Firebase et. al that I mentioned)

brianosaurus00:04:21

Does anyone have any job scheduler recommendations? I’m thinking of http://clojurequartz.info/ but wondering if anyone has any better ideas? We need to run things at various times and persist the schedule in a database.

anmonteiro00:04:54

that said, it’s not meant for every use case and for every application. But definitely a huge improvement over existing stuff if you’re building an application with such requirements

adambrosio00:04:57

(disclaimer: i haven’t used it yet, but I’ve been looking for a scheduler myself)

brianosaurus00:04:08

adambros: thanks. I didn’t see it mentioned anywhere wether or not it persists the schedule to a db. Does it?

adambrosio00:04:54

it seems to be more abstract, in that you define a handler and install it on a schedule

adambrosio00:04:51

oh i see i misunderstood

adambrosio00:04:02

let me take a look

adambrosio00:04:14

from what i can tell it just uses a var hara.io.sheduler/*defaults*, so no?

brianosaurus00:04:14

Well, thanks regardless @adambros

amashi00:04:42

@anmonteiro: I think I am failing to understand some things here (almost certainly because of my own deficiencies.) Most systems I've built do not allow clients to alter data, wherever it lives, without at least a bit of central validation. Am I misunderstanding you?

anmonteiro00:04:35

well you can obviously validate stuff on the server

anmonteiro00:04:04

what I meant is the ability that clients have to communicate the creation / updates of such data

anmonteiro00:04:19

that is much more evolved from the way we’re used to today

amashi00:04:36

I really do think I am failing to understand something here.

anmonteiro00:04:04

what are you not understanding?

anmonteiro00:04:19

I can give you an example

amashi00:04:40

But let's say I write an app that hits some endpoint and in some ways makes it update a datastore.

amashi00:04:50

How is that different?

anmonteiro00:04:36

in that scenario, would you be e.g. able to create non-trivial temporary data on the client, communicate it to the server, and have it send you just the mappings from the temporary ids to the real, persisted IDs?

anmonteiro00:04:53

Om Next makes this scenario really simple

amashi00:04:50

OK, so the advantage here is mainly about synchronization?

anmonteiro00:04:06

I do believe so, yes

anmonteiro00:04:15

this is why I mentioned things like meteor and firebase

amashi00:04:19

That's a story I am very willing to buy, if so...

amashi00:04:50

You have no idea how much code I have written to keep things in sync manually in the last year or so.

amashi00:04:01

Between mobile apps, remote dbs, etc.

anmonteiro00:04:05

I’m certain that’s something you’re looking for, as per your comment regarding optimistic updates and rollbacks

anmonteiro00:04:27

that’s another selling point for Om

anmonteiro00:04:11

2 lines of code

amashi00:04:18

right- well for instance in a recent app I wrote all my updates have to be optimistic, but...

amashi00:04:44

Is the point here simply that the app-state can be rolled back to what it was before the update if it fails?

amashi00:04:54

Or am I missing something really important?

tony.kay03:04:10

To anyone interested: I just finished the first recipe on the cookbook. I'm not planning on making them pretty myself...so anyone interested in adding a bit of CSS love is welcome to do so. The recipe (tabbed-interface) includes some tidbits that will had wide interest: - How to leverage a union query to switch in/out different bits of UI at the same place - How to lazy-load data (in Untangled) during a mutation that is doing something else entirely (e.g. switch tabs also triggers a server load) https://github.com/untangled-web/untangled-cookbook/tree/master/recipes/tabbed-interface

tony.kay03:04:42

This uses 0.4.7-SNAPSHOT, which I've put on clojars. WARNING: It requires om-alpha32 (there were renames from 31->32)

tony.kay03:04:01

if you don't mess with the project file, it should be fine

tomjack04:04:56

I've been wondering about the "pass mutation to children" thing

tomjack04:04:16

in this case, doing the mutations in the children but putting :current-tab in a follow-on read wouldn't work?

tony.kay04:04:30

Did you read the example already?

tony.kay04:04:32

The client muattion has to change the ident...there is no problem with that...optimistic update (to switch to the tab immediately) is fine. From within that mutation (or as an additional mutation done at the transact level), one can trigger a load in the mutation code. You want this because the UI should not go examining global state...you want an abstract mutation to do the work if it is coming from the UI. Actually, I guess I could make the sample clearer now that you mention it.

tony.kay04:04:26

I separated them into two mutations when in fact they could be combined, which is the point. However, I want them separate in the example so you can see the simplicity of the tab change (one line)...I need to add a comment that the load triggering could easily be combined with the change tab mutation, which is part of the point

tony.kay04:04:37

You don't want to use load-data directly in the UI because some analysis of "what to load" needs to be done as you enter the tab...and the answer might be "nothing"

tony.kay04:04:14

notes added to repo

tony.kay04:04:33

@tomjack: let me know if it needs more clarity

tony.kay04:04:23

Server-side security recipe created with README (HAS NO code yet...but describes a way to do it)

tomjack04:04:47

(it seems to work. I was just wondering if there's something I'm missing about the "pass transact! callbacks down to children" thing)

tomjack04:04:50

the server-side security stuff is interesting

tomjack04:04:19

[*] is kind of puzzling

tony.kay04:04:49

oh...passing callbacks. Have you not seen that in Om?

tomjack04:04:38

I've seen/heard it, I just don't know if I understand the reasons to do it

tony.kay04:04:24

Basic rule of list/collection management (and I would consider sub-tabs a collection of things):

tony.kay04:04:41

1. Transactions that affect the collection should be done in the parent (owner that renders them)

tony.kay04:04:16

2. If something in the UI of a child needs to trigger the transaction, then you pass it in as a callback (so you're still closing over the parent this in the transact)

tony.kay04:04:19

simple as that

tony.kay04:04:13

you use om/computed to pass callbacks because that causes the callback to be recorded "out of band" from the query result. This is needed because the sub-component can be re-rendered without re-rendering the parent...but it only gets the updated database query (which would lose the callbacks)

tony.kay04:04:51

Way back in like om-alpha12 you just passed the callbacks in the property map (e.g. via assoc)...then we discoverd that problem

tomjack04:04:56

but.. if I simply do the transaction in the child, and use an appropriate follow-on read in the tx, then I can ignore the rule with no bad effect?

tony.kay04:04:10

good question

tony.kay04:04:37

I know that David N. made up this rule, and it was hard to get clarification of why exactly. If I had to guess (which should be pretty good): If you do the follow-on read I think you might get a double-render (re-render the child, then re-render the parent from the follow-on, which will again re-render the child)

tony.kay04:04:50

not sure that matters in 99% of the cases

tony.kay04:04:59

follow-on reads are really about updating things "elsewhere", so in concept you're right, but I think elsewhere is intended to be other branches of the tree, not the immediate parent. But my strong suspicion is that it is just a rendering optimization rule

tony.kay04:04:22

Also, in principle, I guess it is best to not make children have to know about things that you really don't need to know about. The callback method makes it possible to make a subcomponent that can be used in any parent

tomjack04:04:27

oh, right, the current tab/navbar situation is different..

tony.kay04:04:30

the follow-on read couples the two together

tomjack04:04:47

thanks, I'll try not following the rule and keep an eye out for stuff like that

tony.kay04:04:06

sure...now that we've talked about it, I think the component isolation is a better reason

tomjack04:04:43

ah, right, was wondering if there was any 'good practice' about it

tony.kay04:04:11

follow-on read couples you to a specific UI structure (loosly). Callbacks don't

tony.kay04:04:25

I take that back

tony.kay04:04:50

follow-on reads are about abstraction...this mutation causes this other dependent data to change. You should not care if that is a parent...or even know

tony.kay04:04:06

[(add-friend) :friend-count]

tony.kay04:04:22

you know that adding a friend affects the friend count, but you should not care where that is rendered. Completely decoupled fro m UI...coupled only to the abstraction

tony.kay04:04:33

[(add-item-to-list) :parent-prop]

tony.kay04:04:47

couples the mutation to the idea it is embedded in a child that has a parent

tony.kay04:04:10

But I cannot think of a technical reason why the latter would fail to work

tony.kay04:04:01

ok...long day. Headed to bed. Thanks for looking at the cookbook

tomjack04:04:14

thanks for making it!

therabidbanana16:04:51

Another thought for the cookbook - query caching, along the lines of the om example would be great to see - I can see us serving a lot of cacheable stuff from our queries: https://github.com/omcljs/om/wiki/Remote-Synchronization-Tutorial

tony.kay18:04:01

Add it to the wiki simple_smile

therabidbanana20:04:16

Done, just throwing out here in case other people want to pile on or bring up good info I might not have seen. 😄

leontalbot20:04:03

Hi untanglers! Are there uses cases for a CMS / static site generator using untangled? Would you use untangled to create a CMS that a non-tech client can control?

leontalbot20:04:33

I'd like to try datomic for a new projet and it seems the integration untangled + datascript + datomic is very natural

leontalbot20:04:52

Not sure though if a CMS/blog app could be a good fit...

adambrosio20:04:16

personally ive been wanting to make a CMS with it, but I’m not sure I understand your question. What are you looking for in untangled to help you make a CMS?

tony.kay20:04:03

We're actually building a template/HTML component in house (prob won't be open source though)...@adambros worked on it

tony.kay20:04:59

We're not directly supporting DataScript on the client, though you can hook it in.

tony.kay20:04:01

I'm recommending you keep the UI database to the Om default format. If you also want a Datascript db on the client, then you'd have the two interact/coordinate. Rendering directly from DataScript seems like a good idea on the surface, but in practice not good (performance, schema, etc)

tony.kay20:04:56

you'd typically want your datascript to mirror your Datomic...and if you study Untangled at all (or Om) you'll see that it is rare for your UI structure to match your schema graph.

tony.kay20:04:18

so, you have to do a transform anyhow, which is the Om parser...but in Untangled, we eschew that for a more direct data manipulation approach

leontalbot20:04:43

@tony.kay @adambros So I guess I should forget about datascript for now. So the db will be available on the server side (datomic). It will provide the content to Om/Untangled-client that will load it up front to constitute the state? I guess I would need an example of a datomic connected to untangled (without datascript) Are there any?

leontalbot21:04:23

(As you can see, I am not a senior developer, forgive me for that!)

tony.kay21:04:46

well, a decent amount simple_smile

tony.kay21:04:11

Please see the resources on the website, and on github. TodoMVC, Tutorial, Cookbook (new, but has a few things in it)

tony.kay21:04:35

Ah, specifically connected to datomic: we're persisting todomvc in datomic, I think

tony.kay21:04:44

in-memory, but all you change is a URL

tony.kay21:04:57

The tutorial does describe a lot of it

leontalbot21:04:08

Will start there I guess. Thanks a lot!

tony.kay21:04:35

sure, there is a lot to document still...so be prepared to dig a little. Trying to remedy that as quickly as possible

leontalbot21:04:11

If I find an opportunity to help in the doc, I will. But can't promise 😉

leontalbot21:04:33

I need to stay humble first 😉

tony.kay21:04:11

appreciate anything you feel like helping with. As a beginner, start simple...don't try to do it all at once

iwankaramazow21:04:30

@tony.kay I just finished an initial implementation of a client side router focused on om next, see #C06DT2YSY or https://github.com/IwanKaramazow/om-router If I need to provide some specific hooks for Untangled, let me know. The plan is to evolve this thing in something useful...

tony.kay21:04:00

New version of the Clj West talk up: https://youtu.be/TU9hWTZcKy0

cjmurphy22:04:22

tabs state is already normalized. So to get the whole of the state all together need to use some tree->db. And this seems to do the job okay:

(def merged-state (atom (merge state/already-normalized-tabs-state (om/tree->db ui/non-union-part-of-root-query state/initial-state true))))
(pprint @merged-state)
. However I'm finding that the om.next/tables set doesn't contain the tables of the tabs, and I'm getting a difficult to debug error as well. Maybe I'm doing something obviously wrong?

currentoor23:04:47

I'm randomly getting a bunch of warnings like WARNING: Use of undeclared Var om.util/join-key in untangled/client/impl/data_fetch.cljs

currentoor23:04:02

on master, this code was working fine a few days ago

currentoor23:04:30

I've got the same version of om "1.0.0-alpha31" as the untangled repo.

ethangracer23:04:28

@currentoor: you’ll need alpha32 starting with 0.4.7-SNAPSHOT

cjmurphy23:04:08

The difficult to debug error is from the same line that gives this compiler warning:

cjmurphy23:04:09

WARNING: Use of undeclared Var om.util/ident? at line 27 resources/public/js/compiled/dev/untangled/client/impl/om_plumbing.cljs

cjmurphy23:04:12

.. think I'll try alpha32 as well...

cjmurphy23:04:26

Yes that fixed it - SNAPSHOTs can change beneath your feet!