Okay, I finally made it. Here is the implementation:
(defn- read-map
[db]
(or (first (d/q '[:find ?e ?v :in :where [?e :map ?v]] db)) [nil nil]))
(defn- write-map
[conn fn]
(let [[old-id old-val] (read-map @conn)
new-id (if old-id {:db/id old-id} {})
new-val (or (fn (or old-val {})) {})]
(d/transact! conn [(merge new-id {:map new-val})])))
(deftype DatabaseWrapper [db]
IDeref
(-deref [_]
db)
ILookup
(-lookup [this k]
(-lookup this k nil))
(-lookup [_ k not-found]
(let [[_ map] (read-map db)]
(if (nil? k)
map
(or (get map k) not-found)))))
(deftype DatabaseCursor [conn]
IAtom
IDeref
(-deref [_]
(DatabaseWrapper. @conn))
ILookup
(-lookup [this k]
(-lookup this k nil))
(-lookup [this k not-found]
(-lookup @this k not-found))
IAssociative
(-contains-key? [this k]
(not (= (-lookup this k ::not-found) ::not-found)))
(-assoc [this k v]
(write-map conn #(assoc % k v))
this)
IMap
(-dissoc [this k]
(write-map conn #(dissoc % k))
this)
ICloneable
(-clone [this]
this)
IHash
(-hash [_]
(hash @conn))
ISwap
(-swap! [_ fn]
(write-map conn #(fn %)))
(-swap! [_ fn x]
(write-map conn #(fn % x)))
(-swap! [_ fn x y]
(write-map conn #(fn % x y)))
(-swap! [_ fn x y xs]
(write-map conn #(fn % x y xs)))
IMeta
(-meta [_]
(meta conn))
om/ITransact
(-transact! [_ _ _ _]
(throw js/Error "not supported"))
om/IValue
(-value [_]
@conn)
om/ICursor
(-path [_]
[])
(-state [_]
nil)
IEquiv
(-equiv [_ other]
(if (instance? DatabaseCursor other)
(= @conn @@other)
(= @conn other)))
IWatchable
(-notify-watches [_ oldval newval]
(-notify-watches conn oldval newval))
(-add-watch [_ key f]
(-add-watch conn key f))
(-remove-watch [_ key]
(-remove-watch conn key))
IPrintWithWriter
(-pr-writer [_ writer opts]
(-pr-writer @conn writer opts)))
A new cursor can be simple created with
(DatabaseCursor. (d/create-conn {}))
Now when you enable instrumentation
(defn- instrument
[f cursor m]
(let [custom-opts (assoc m :descriptor (om/no-local-descriptor
om/no-local-state-methods))]
(om/build* f cursor custom-opts)))
local state will be saved to the DataScript db.
Stephan
On Sunday, January 25, 2015 at 11:09:25 AM UTC+1, stephanos wrote:
> Hey there,
>
> I'm trying to integrate Om and DataScript.
>
> At first I used David Nolen's gist [1] that implements 'om/IToCursor' for
> DataScript's DB type. That worked out well for some time. But now I try to
> apply Om's experimental support for writing all local state into the app
> state [2]. This requires an associative data structure because of its use of
> 'assoc' and 'get-in'.
>
> So I attempted to write a wrapper around the DataScript DB atom,
> DatabaseCursor. Now, while I succeeded in saving the local state to it by
> implementing IAssociative and ILookup, the app does not re-render on change
> anymore :(
>
> I originally assumed all I needed was to implement the IEquiv or IHash
> protocol, but that does not seem to work (both are never called). So I'm
> stuck right now. Here is my DatabaseCursor:
>
> (deftype DatabaseCursor [conn]
> ILookup
> (-lookup [this k]
> (-lookup this k nil))
> (-lookup [_ k not-found]
> (let [v (ffirst (d/q '[:find ?v :in $ ?k :where [?e :key ?k] [?e :value
> ?v]] @conn k))]
> (or v not-found)))
> IAssociative
> (-contains-key? [_ k]
> (not (empty? (d/q '[:find ?e :in $ ?k :where [?e :key ?k]] @conn k))))
> (-assoc [this k v]
> (let [old-id (ffirst (d/q '[:find ?e :in $ ?k :where [?e :key ?k]]
> @conn k))
> new-id (if old-id {:db/id old-id} {})]
> (d/transact! conn [(merge new-id {:key k, :value v})]))
> this)
> om/IToCursor
> (-to-cursor [this _] this)
> (-to-cursor [this _ _] this))
>
> How to I need to modify my custom cursor to make Om aware of changes to the
> DataScript DB?
>
> [1] https://gist.github.com/swannodette/11308901
> [2]
> https://github.com/swannodette/om/commit/ee9d92bf1191a391df804c066868c8180f9d64cf
--
Note that posts from new members are moderated - please be patient with your
first post.
---
You received this message because you are subscribed to the Google Groups
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.