This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-17
Channels
- # admin-announcements (3)
- # announcements (1)
- # aws (3)
- # beginners (41)
- # boot (109)
- # braid-chat (2)
- # braveandtrue (5)
- # cider (11)
- # cljs-dev (38)
- # cljsjs (15)
- # cljsrn (5)
- # clojure (87)
- # clojure-berlin (16)
- # clojure-ireland (1)
- # clojure-japan (10)
- # clojure-madison (3)
- # clojure-nl (3)
- # clojure-poland (6)
- # clojure-russia (115)
- # clojure-sg (1)
- # clojurebridge (35)
- # clojured (8)
- # clojurescript (36)
- # core-async (24)
- # cursive (18)
- # datavis (1)
- # datomic (27)
- # dirac (22)
- # editors (1)
- # emacs (3)
- # events (19)
- # hoplon (149)
- # ldnclj (7)
- # lein-figwheel (1)
- # luminus (1)
- # off-topic (70)
- # om (196)
- # onyx (63)
- # parinfer (155)
- # proton (36)
- # re-frame (69)
- # reagent (2)
- # ring (2)
- # ring-swagger (1)
- # slack-help (4)
- # spacemacs (9)
- # testing (11)
hey, so i have a q about how attributes work inside a loop-tpl
i did this (using datascript):
(defc= sorted-values
(concat
(->>
(d/q '[:find ?id ?data :where [?id :data ?data]] conn)
(sort-by first))
'([nil nil])))
(loop-tpl :bindings
[[id data] sorted-values]
[(if (not= @data "")
(input
:value data
:data-id @id
:input #(d/transact! conn
(if @id
[{:db/id @id :data @%}]
[{:data @%}]))
:keyup #(if @id (d/transact! conn
(if (= "" @%)
[[:db.fn/retractEntity @id]]
[{:db/id @id :data @%}]))
so, the :value
updates as i expect (the conn
is a cell so every time i update the db it reflows the inputs)
but the :data-id
doesn’t seem to update at all once an input has been created
tries not to deref
also, cells + datascript is really cool
is there an easier way to do it than
(defn conn-cell-from-db
"Mimics datascript conn-from-db but builds a compatible javelin cell"
[db]
(cell db :meta { :listeners (atom {}) }))
i mean, that’s easy, but is there a more “right” way?
I have a little cell-q
helper:
(defn cell-q [query & params]
((formula #(apply d/q query % params)) db))
yay, works, @dm3 thanks
aah cool, well i noticed that the only thing datascript checks for to see if conn
is valid is IDeref
so i just used a cell
instead of an atom and rewrote it
you can use transact!
straight on the cell then
do you know if anyone pinged tonsky about a direct collaboration?
hoplon + datascript seems like a great match
basically something like what i did above, but also “officially” not doing anything that would break cells
very little would need doing now
but of course i’m nervous that the api might shift in the future...
i’ve got bigger problems right now
like being a n00b 😉
is there a way to do a loop-tpl
with a let
@dm3 ?
or is that supposed to be :bindings
hang on
(loop-tpl :bindings [
data (d/q '[:find ?id ?data :where [?id :data ?data]] conn)
sorted (sort-by first data)
sorted+final (concat sorted '([nil nil]))
[id data] sorted+final]
like that
doesn’t work
(defc= inputs-state (let [
state (d/q '[:find ?id ?data :where [?id :data ?data]] conn)
sorted (sort-by first state)
sorted+final (concat sorted '([nil nil]))]
sorted+final))
(u/outer-dom
(u/the-header)
(main :id "main"
(loop-tpl :bindings [[id data] inputs-state]
that works though
@dm3: does that make sense?
so :bindings
doesn’t like things that aren’t cells?
is there any particular overhead to nesting cell=
?
or can i pretty much chain it as much as i want?
otherwise you just need to keep in mind that when anything in the database changes, all of your queries will get rerun
ah yeah, for re-running queries, that’s obvious
but say...
(defc= inputs-state (let [
state (d/q '[:find ?id ?data :where [?id :data ?data]] conn)
sorted (sort-by first state)
sorted+final (concat sorted '([nil nil]))]
sorted+final))
(defc= state (d/q '[:find ?id ?data :where [?id :data ?data]] conn))
(defc= state:sorted (sort-by first state))
(defc= state:sorted+final (concat state:sorted '([nil nil])))
i had hoped so
sounds good
@dm3 also, do you have any experience with what “too big” might be in practice?
before you notice queries getting sluggish
haven’t figured that out yet
i wrote my first datascript query yesterday 😛
I've abandoned that idea as either you have a mirror db on the server for each client or you have a headache of mapping entity ids between different dbs
so currently I'm working with the model where a client generates an event, applies it to the db locally and sends to the remote which then gets propagated to other clients
what do you mean by “an event”?
oh yeah, i saw someone had some code to push the transactions to the remote
no good?
you just lose some of the clarity if you need to do some complicated actions in response to a transaction
why would you need to perform complicated actions on the remote in response to syncing transactions?
wouldn’t you do the complicated stuff in the client and then just push the transactions through as-is?
ah, i had thought that was what the transactor was supposed to help sort out
is that wrong?
because it’s serial
isn’t there a datomic thing somewhere?
you can either adopt a dumb strategy of "last update wins" - and that works for a huge amount of cases
have something like CRDT where the updates are monotonic and conflicts resolved automatically
or make decisions intelligently based on what happens (events) - e.g. operational transformation (how google docs work)
well the transactions have times on them don’t they?
if you had a datomic
wouldn’t you get both updates, with a log, and the current on is “last update wins”?
*haven’t actually used datomic*
oh yeah
but the difference is you’d have an audit trail
if you were a user and were like “wtf just happened?"
you’d see “you updated” and “bob updated 5 seconds after you”
ok sure, so yeah
you need to make something domain specific
to keep track of “what happened"
where “what happened” is a bit easier to understand than a stream of transactions
what do you normally work on?
also, is there a reason to specifically not use datomic?
it seems like it would be useful for keeping everything in check
wow, lotta cool datascript/cells goin on i nhere
yeah, learning about it
i had written something in ~80 lines that used a vector storing state in localStorage
trying to get the same thing in ~40 lines with datascript
probably as much as i can do tonight
hopefully I’ll get my tests passing tomorrow
(defn conn-cell-from-db
"Mimics datascript conn-from-db but builds a compatible javelin cell"
[db]
(cell db :meta { :listeners (atom {}) }))
(def conn (local-storage (conn-cell-from-db (d/empty-db {})) ::conn))
(defc= state (d/q '[:find ?id ?data :where [?id :data ?data]] conn))
(defc= state:sorted (sort-by first state))
(defc= state:sorted+final (concat state:sorted '([nil nil])))
(defn attribute-selector
([attribute] (str "[" attribute "]"))
([attribute value] (str "[" attribute "=\"" value "\"]")))
(u/outer-dom
(main :id "main"
(loop-tpl :bindings [[id data] state:sorted+final] [
(input
:value data
:data-id (cell= (or id "final"))
; input occurs on keydown but after the input's value has been updated
; c.f. keydown that occurs before the value has changed.
:input #(d/transact! conn
(if-not (= "" @%)
(if-not @id
; create
[{:data @%}]
; update
[{:db/id @id :data @%}]
)
(if @id
; delete
[[:db.fn/retractEntity @id]])))
; Move the cursor on keyup for certain states. This allows the DOM to
; fully reflow from db updates before we try to jump the user's
; context around.
:keyup #(let [
input-blank? (= "" @%)
backspace? (which-key/pressed? :backspace %)
enter? (which-key/pressed? :enter %)
select-last-id! (fn [] (do! (attribute-selector "data-id" (-> @state:sorted (last) (first))) :select))
select-final-input! (fn [] (do! (attribute-selector "data-id" "final") :select))]
(cond
(and input-blank? backspace?) (select-last-id!)
enter? (select-final-input!))))])))
@onetom: that’s where i got to tonight, if you’re wanting to play around
the real advantage will be moving from individual inputs (which is about all i could easily manage with a vector) to a variety of form elements
keen to try and do that
Anyone have an idea why png’s are getting a 404 in my app?
Ah! I figured it out! :asset-paths #{"resources/assets”}
is not on the class path