Now there is still one problem.

If the database is filled with data already (e.g. when loading data from 
localstorage into it upon page refresh), it is overridden by Om since it calls 
'init-state' and uses swap! + assoc to put the database in the global state.

@David Would it make sense to use 'merge' instead? In order to respect the data 
that exists prior to the first 'init-state' call?

Stephan


On Saturday, January 31, 2015 at 4:39:45 PM UTC+1, stephanos wrote:
> 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.

Reply via email to