Clojurians
#om
<
2016-01-24
>

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

cascada-io01:01:48

nothing reference-cursor-ish yet in om.next, correct?

jlongster02:01:59

@cascada-io: no cursors at all, queries instead

jlongster02:01:43

I noticed in the parser comments that there is a :union type. shouldn't (om/query->ast '{:foo [:x] :bar [:y]}) return { :type :root, :children [{ :type :union ... }]} ?

mdhaney02:01:19

@jlongster: for a simple app, you could always use Datomic in memory db, and listen to the transaction log and write transactions to a log file. Main drawback is your entire dataset has to fit in memory, but if you just have a small-ish dataset and want Datomic's querying abilities, it might be a viable option.

jlongster02:01:29

@mdhaney: I could, don't really want to handle that transaction logging & rebuilding the db though. also my data fits well with the relational model & it's kind of queries. most importantly, I feel like it's super cool to show how easy it is to use anything with om next

mdhaney02:01:16

@jlongster: fair enough. And yes, showing that flexibility is super cool. I'm working on what sounds like something similar for a prototype at work. Difference is, the backend is all microservices instead of a db.

jlongster02:01:21

nice. I may try datomic at some point, but I don't like that people think om next only integrates with it

jlongster02:01:45

any posts, etc showing other things would be great

cascada-io02:01:01

jlongster: question was whether a new (non-cursor obv) pattern/feature has surfaced to solve the problem reference cursors solved in om.now

cascada-io02:01:47

(namely: deeply nested component has a data dependency not passed to it by its parent)

jlongster02:01:05

@cascada-io: still learning om next myself, not far enough in to give a good answer, but generally things work better simple_smile

mdhaney02:01:53

@cascada-io: I think a big part of the design of om-next was based on solving that problem. Look at the Thinking in Links tutorial on the Om wiki.

cascada-io02:01:55

@mdhaney: yes, i've been looking at that and playing w/ it, but not seeing any way to avoid passing props all the way down (and no component in that example using data that wasn't directly passed to it)

cascada-io02:01:22

(not entirely accurate... :current-user does so. not quite comparable to reference cursors though)

jannis09:01:41

@cascada-io: There is no way to avoid passing props down. That's how it works. Components define queries and they expect to receive the corresponding data. If you don't pass that down, you're breaking their input contract. There are at least two ways to reference "top-level data" in Om Next: One is to use links, specifically [:top-level-data _] (note the underscore), the other is to use :shared/ :shared-fn: https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L1711 - I believe :shared-fn is run on every render.

simonb11:01:51

I made a demo of localisation with Om Next and DataScript https://github.com/bnomis/om-next-datascript-localisation-demo

nxqd11:01:28

@simonb: your app looks pretty neat.

simonb11:01:01

@nxqd: Thanks

nxqd11:01:25

@simonb: I can see that multilingual sites should become the standard now. I think if you have some kind of a translation bar ( for translator ) so he or she can translate the app by click to translate mode then he or she can translate each code block. It would be very interactive and awesome way to translate. Just my opinion simple_smile

simonb11:01:32

@nxqd: Yep. That's the idea. The app is the authoring tool - used to play/view the content as well as author it.

andrewboltachev12:01:47

Hi. Can't get it working properly recursive component and a wrapping one around it. Using db-tree. Did ~2h debugging and digging into src. Is that true about denormalize* that if data is a vector, it should be vector of idents, not, say, maps (i.e. actual data)? This line makes me think so https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L1244

iwankaramazow12:01:04

Hmm, not sure if you can use the standard

db->tree
if you're working with recursive queries

andrewboltachev12:01:24

inetresting @iwankaramazow

andrewboltachev12:01:44

well, the thing I'm trying to get from Om Next is one it's intended to be best at — handling all these queries (i.e. co-located ones, recursive etc, all together) right

iwankaramazow12:01:54

check out https://awkay.github.io/om-tutorial/#!/om_tutorial.E_State_Reads_and_Parsing Excellent example if you want to parse recursive queries

andrewboltachev12:01:29

Great, thanks @iwankaramazow !

anmonteiro12:01:57

@andrewboltachev: you can also use path optimization in recursive queries, and db->tree will work then

andrewboltachev12:01:52

@anmonteiro: so, either would it miss that line (and case (vector? data)), or idents will appear? simple_smile

anmonteiro12:01:17

this is an extra thing, which is only triggered after mutations

iwankaramazow12:01:17

So at the moment what can't db->tree handle? Only query params?

andrewboltachev12:01:05

'cause I did (om/db->tree query @state @state)

anmonteiro12:01:37

@andrewboltachev: (om/db->tree query @state @state) won't work as you expect

anmonteiro12:01:49

that will just denormalize the whole state

anmonteiro12:01:11

and you'll get repeated keys in your return from read

anmonteiro12:01:17

like, one more level of nesting

andrewboltachev12:01:37

I just were trying to read keys from the root of the state

andrewboltachev12:01:40

Though as I learnd, [[:foo :bar] _] is in charge of it

iwankaramazow12:01:54

@anmonteiro: if you have a query like [{:foo [:bar :baz { :other {:subproperty :anotherproperty}} }], you need to call your parser recursively. Am I correct? This is not something om/db->tree can deal with?

anmonteiro12:01:08

@iwankaramazow: not sure that query is valid

andrewboltachev12:01:39

@iwankaramazow: what that { :other {:subproperty :anotherproperty}} nested maps do?

iwankaramazow12:01:55

The above query is: ({:results [:place :agegroup :time :year {:person [:name :firstname]}]} {:year 2016})

andrewboltachev12:01:16

I'm starting to understand why GraphQL's spec is so huge: https://facebook.github.io/graphql/ simple_smile

andrewboltachev12:01:26

well, let's check what I have: [{:categories [{:categories/list [:db/id]}]}]

iwankaramazow12:01:52

what does your data look like?

anmonteiro12:01:33

@iwankaramazow: that second one is indeed valid

anmonteiro12:01:46

does db->tree not handle it?

andrewboltachev12:01:15

{:categories/list [
 {:db/id 1
  :category/name "foo"
  :category/_parent [
   {:db/id 2
    :category/name "bar"
    }
   {:db/id 3
    :category/name "buz"
    }]
  }
 }

anmonteiro12:01:16

I think there's an issue for that; I'm happy to look at a minimal case

iwankaramazow12:01:21

@anmonteiro: console.log gives me Uncaught Error: Doesn't support name: {:person [:naam :voornaam]}

bbss12:01:23

Sure you don't need :persoon ? 😉

andrewboltachev12:01:25

@bbss: I think that different languages have differences

iwankaramazow12:01:44

forget the translation part

bbss12:01:07

he is using naam and voornaam which are dutch and person would be persoon in Dutch

iwankaramazow12:01:20

Uncaught Error: Doesn't support name: {:person [:name :firstname]} 😛

andrewboltachev12:01:30

ah, Dutch that is 😄

iwankaramazow12:01:47

my parser could be wrong

andrewboltachev12:01:04

I were thinking @bbss you treat that as sth funny. Sorry 😐

bbss12:01:26

I was hahah, but it's still possible to mess that up when mixing languages

anmonteiro12:01:31

@iwankaramazow: probably a bug, there's https://github.com/omcljs/om/issues/558 which also reports the same

bbss12:01:49

I am actually also right now writing a parser

anmonteiro12:01:50

so if you share a minimal case I'm happy to look at it and discuss a patch with David

bbss12:01:21

I am a bit confused by some data in the default database format, from:

(om.next/db->tree query some-data app-state-db)
Given a query expression, some data in the default database format, some application state data in the default database format, denormalize it. This will replace all ident link nodes with their actual data recursively. This is useful in parse in order to avoid manually joining in nested relationships.

iwankaramazow12:01:42

@anmonteiro: I'll put a minimal case together

anmonteiro12:01:49

@iwankaramazow: thanks!

bbss12:01:57

what is the meaning of "some data" when there is already "some data" in the app state

andrewboltachev12:01:18

in a snippet just above, (:tree st) is "some data"

iwankaramazow12:01:27

the way I remember it the app-state contains something like: [[:results/by-id 1] [:results/by-id 2]]

iwankaramazow12:01:47

state is just your state deref'ed

iwankaramazow12:01:00

and query is the query 😛

andrewboltachev12:01:26

well, some-data is piece of state query is applicable on

andrewboltachev12:01:34

i.e. not the whole state

bbss12:01:46

@andrewboltachev: you mean " {:value (om/db->tree query (get st k) st)}))" ?

andrewboltachev12:01:14

I've seen exactly that somewhere...

iwankaramazow12:01:56

@bbss: that's it

bbss12:01:24

Thanks, that got me a step closer simple_smile

bbss12:01:41

I thought it should have been that but "some data" was just too vague.

andrewboltachev12:01:31

well, yep that seems to be just quick solution

andrewboltachev13:01:10

@iwankaramazow: and what's your data like?

andrewboltachev13:01:28

{:results {:place 1
                      :agegroup 2
                      :time 3
                      :year 2016
                      :person {:name 5 :firstname 6}
                      }

            }

iwankaramazow13:01:20

In denormalized form it's something like:

{results    [[:results/by-id "1501"]]
   :results/by-id {"1501" {"id" "1501" "plaats" "1" "person" [:person/by-name "DewildeKristof"] "categorie" "H3" "tijd" "00:53:16" "jaar" "2015"}}
   :persons [[:person/by-name "DewildeKristof"]]
   :person/by-name {"DewildeKristof" {"naam" "Dewilde" "voornaam" "Kristof"}}} ) 
(dutch version)

andrewboltachev13:01:56

btw, there are strings: "naam"

iwankaramazow13:01:24

yea my read function translates them to keywords

andrewboltachev13:01:13

btw, db->tree operates independant of read-fns, isn't it?

iwankaramazow13:01:54

yes, just supply it with the necessary params

andrewboltachev13:01:57

I wonder if I my error is similar to yours one, but seems no

iwankaramazow13:01:22

@anmonteiro: by throwing it in a gist, taking another look at it, that bug disappeared like magic 😬

anmonteiro13:01:24

@iwankaramazow: also disappeared from your app?

iwankaramazow13:01:47

yea, db->tree works fine now. Transit converts a json response to strings in my app, so no keywords, they're all string My queries contained keywords, not strings, I failed to convert them at some point...

robert-stuttaford13:01:56

has anyone got code to om/set-query! via a mutation?

andrewboltachev13:01:32

@robert-stuttaford: you mean inside of :action?

robert-stuttaford13:01:33

i actually just want to change the QueryParams

robert-stuttaford13:01:47

is it really as simple as i think it is?

iwankaramazow13:01:00

it probably is 😇

anmonteiro13:01:16

@robert-stuttaford: you might want to look into update-query!

andrewboltachev13:01:22

@robert-stuttaford: is that :action, is set-query! the only thing you want to do, or something else too?

andrewboltachev13:01:38

@anmonteiro: How about this:

(println 
  (let [data
        {:items [
                 {:id 1
                  :name "hello"}
                 {:id 2
                  :name "world"}
                 ]
            }
        ]
    (println "result is"
         (om/db->tree
              '[{:items [:id :name]}]
           data
           data
           )
      ; returns {:items [{} {}]}
      )
    )
  )

andrewboltachev13:01:06

(that's minimal case of my appeal to db->tree)

andrewboltachev13:01:51

@robert-stuttaford: I mean, don't you trying to store copy of your query params in state also?

robert-stuttaford13:01:31

the query-param is a datomic lookup ref

robert-stuttaford13:01:37

i’m writing a generic datomic browser

robert-stuttaford13:01:16

just need one mutation to switch the lookup ref to some new entity, which will fetch it and repopulate the state with that entity’s data

robert-stuttaford13:01:23

giving me repeatable forward nav

anmonteiro13:01:49

@andrewboltachev: that's not a bug

anmonteiro13:01:01

your data is already denormalized, why are you calling db->tree on it?

anmonteiro13:01:23

this works as expected:

(def data {:items [[:item/by-id 1] [:item/by-id 2]]
           :item/by-id {1 {:id 1 :name "hello"} 2 {:id 2 :name "world"}}})

(om/db->tree [{:items [:id :name]}] data data)

andrewboltachev13:01:38

@anmonteiro: oh indeed...

andrewboltachev13:01:31

@anmonteiro: still the same goal — I wanted Om to read data for all my components

andrewboltachev13:01:47

I tried to use db->tree w/o much thinking

andrewboltachev13:01:17

i.e., I were thinking it's right to "read data for hierarchy of components"

andrewboltachev13:01:56

so, I'll get into all that links (mostly your blog but not only) and find a solution then. Thanks

andrewboltachev13:01:35

so today's score is 2:0, Om vs. users

andrewboltachev13:01:01

iwankaramazow hasn't had a bug and me too

andrewboltachev13:01:10

@robert-stuttaford: I think you might use set-query! / update-query! directly from your event handlers (e.g. button click), no need for additional transact! call

robert-stuttaford13:01:05

is there a trick to getting a reference to the component you’re updating from inside that component?

iwankaramazow13:01:35

(om/class->any) ?

anmonteiro13:01:38

@robert-stuttaford: use this ?

robert-stuttaford13:01:53

thanks anmonteiro. ok. i’m SUPER close

robert-stuttaford13:01:04

scratch that. it’s working simple_smile

robert-stuttaford13:01:00

thanks for your help, folks

andrewboltachev13:01:33

But funny. db->tree (and friends) don't even care about components. ident? and other predicates are used to figure out the type of the (sub)expression. Such "duck typing"

andrewboltachev13:01:52

From the other hand can't say other way (e.g. through metadata etc) efficient

dnolen14:01:25

@andrewboltachev: anything involved in query that deals with idents will need to know the component associated with a particular query to be able to invoke ident

dnolen14:01:34

but the issue is more subtle than any of this.

dnolen14:01:59

we don’t have a typed schema a la GraphQL which brings it’s own host of issues I’m not interested in

andrewboltachev14:01:04

well should be in JS world they probably don't have such freedom of thought, always trying to be modest

dnolen14:01:52

hrm? I don’t follow

dnolen14:01:58

Facebook clearly likes typed stuff

dnolen14:01:09

compare to Netflix Falcor which doesn’t bother with the typed schema bits either

dnolen14:01:13

both are JS

andrewboltachev14:01:48

everything should be protected etc

andrewboltachev14:01:13

I wonder about such huge doc on GraphQL

andrewboltachev14:01:20

though I didn't read it

dnolen14:01:35

the doc is quite informative and directly influenced Om Next

dnolen14:01:38

definitely worth reading

dnolen14:01:30

focus on unions were definitely inspired by it, and some of thinking about recursive queries

dnolen14:01:35

though we borrow more from Datomic there

andrewboltachev14:01:41

What I think ppl loose is appealing to some fundamental things like math. Category theorists say that for graph (of some kind, I don't remember) exists free category. I guess that there a lot more "free" stuff exists for graphs, and we can borrow from it

iwankaramazow14:01:12

Not sure if a type system really delivers what it promises.

andrewboltachev14:01:35

I wrote my own small library once https://github.com/andrewboltachev/regexpforobj/blob/master/src/regexpforobj/core.clj#L222 (sth like regular expressions, but "objectified")

andrewboltachev14:01:40

and I think I might optimize it's structure, or even make it trivial via applying sth of math fundamental constucts. Or core.logic (probably to completely replace it) simple_smile

andrewboltachev14:01:40

@iwankaramazow: core.typed does inference, which I believe no one (say, Python 3 with it's "type hints" is doing)

anmonteiro14:01:21

@dnolen: looking into OM-558

anmonteiro14:01:33

hoping you can answer a question

anmonteiro14:01:50

(def data
    {:people [:by-name "Alice"]
     :by-name {"Alice" {:name "Alice" :age 31}}})

(def query '[(:people {:length 3})])

(om/db->tree query data data)

anmonteiro14:01:34

given this snippet, should db->tree return the denormalized version of the data?

bbss14:01:48

is that query correct? isn't that a mutation?

anmonteiro14:01:18

@bbss: it's prop + params

bbss14:01:19

or a getter on a map that doesn't have the key

bbss14:01:31

okay I don't know my query grammar then simple_smile

dnolen14:01:51

@anmonteiro: that’s not a join

dnolen14:01:04

we only follow idents if there’s a join

anmonteiro14:01:25

@dnolen: so it should just return the ident?

dnolen14:01:32

joins “identify pointers” so to speak

dnolen14:01:55

@anmonteiro: that’s what the query says

anmonteiro14:01:02

that's what I thought

dnolen14:01:04

we have no idea that the thing is a ident

dnolen14:01:12

it could be a list from the database

anmonteiro14:01:16

@dnolen: was just confirming. ATM it's returning {}

anmonteiro14:01:24

so, submitting a patch which should solve OM-558

anmonteiro14:01:17

simple fix really

tmorten15:01:48

Hello all...has any one else experienced an issue after returning tempids from a mutation (server side) where after the tempids are merged the query (om.next/query) is reset to nil? In looking at the app-state from repl, the IDs appear to be merged in but client renders nothing...

dnolen16:01:03

@tmorten: haven’t heard of anything like that

dnolen16:01:24

but you should be able reproduce minimally if a bug exists

tmorten16:01:09

@dnolen: I'll build a minimal example to see if I can replicate

a.espolov17:01:02

result for mutate method on server {:value [:abc/abc] :action (fn [] … )} Guys I understand correctly that the key value is needed in order to specify what data you want to return after the execution of the function action?

iwankaramazow17:01:20

with a mutation you don't know what can possibly happen, therefore you just specify what you want to re-read

nxqd17:01:32

@a.espolov: I'm not sure about the keys fn in mutation. But I'm sure that when you mutate like this (om/transact! component [(project/update {}) :project/list)]) on frontend, the related components ( the ones that have :project/list query ) will be rerendered.

a.espolov17:01:21

I get a 500 error to called mutate ‘inspection.review

a.espolov17:01:32

But if I delete the key: value of map mutate method

a.espolov17:01:43

I will get the default value for the read method (defmethod readf :default [ k ] {:value {:error (str "No handler for read sss key " k)}})

a.espolov17:01:15

@dnolen: What am I doing wrong?)

dnolen17:01:29

@a.espolov: no idea

dnolen17:01:54

if you getting a 500 that doesn’t have anything to do with Om

dnolen17:01:02

something about your endpoint

a.espolov17:01:05

endpoint for om parser '(defn api [req] (if-not (authenticated? req) (generate-response {:msg "user unauthorized"}) (generate-response ((om/parser {:read parser/readf :mutate parser/mutatef}) {:conn (:datomic-connection req) :session (:session req)} (:transit-params req)))))'

iwankaramazow17:01:13

try {:value {:keys [:test/test] :action etc.}

a.espolov17:01:36

@iwankaramazow: no this example for front-end

a.espolov17:01:02

@dnolen: my example is based on https://github.com/swannodette/om-next-demo/blob/master/todomvc/src/clj/todomvc/parser.clj but my version of stubbornly doesn't want to work

a.espolov17:01:23

perhaps changed api?

iwankaramazow18:01:47

yea, the todomvc is a little bit outdated

cascada-io19:01:25

is shouldComponentUpdate returning true always? https://www.refheap.com/114012

cascada-io19:01:33

hmm, might be easier to see what's happening here: https://www.refheap.com/114013

cascada-io19:01:20

(bar child re-renders when its data is unchanged)

andrewboltachev20:01:33

@iwankaramazow: @a.espolov Please note that :value :keys are "for documentation purpouses only". To fire a reread one must pass read query after mutations in his transact!

tmorten21:01:13

I have determined in my tests that after a merge of tempids from server-side, the root query is executed again and if you have parameters set, those are also reset. Should this be the proper functionality after merging in remote tempids?

tmorten21:01:21

In other words, if you have parameters set in the query, those will be blown away or set back to whatever you set them to initially with (params [_] ...) .