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