Skip to content

Instantly share code, notes, and snippets.

@jlongster
Last active March 7, 2016 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlongster/1c661626a0860022ef26 to your computer and use it in GitHub Desktop.
Save jlongster/1c661626a0860022ef26 to your computer and use it in GitHub Desktop.
(defn path-meta
([x path]
(path-meta x path nil))
([x path query]
(if (and query (or (map? query) (vector? query)))
(letfn [(strip-params [q]
(cond-> q (seq? q) first))
(descend-into-map-entry [k v]
(path-meta
v
(conj path k)
(let [q (strip-params
;; TODO: check if `query` is a map which
;; happens for union queries. How do we
;; know which subquery to descend with?
(if (vector? query)
(if (= (first query) '*) '* (nth query idx))))]
(if (and (map? v) (map? q))
;; If the value and the query is a map, it was a
;; join that returned a single value. Use the join
;; query specifically
(first (vals q))
q))))]
(let [x' (cond->> x
(map? x)
(into {} (map-indexed
(fn [idx [k v]]
[k (descend-into-map-entry k v)])))
(vector? x)
(into [] (map-indexed
#(path-meta %2
(conj path %1)
(if (map? query)
(first (vals (strip-params query))))))))]
(cond-> x'
#?(:clj (instance? clojure.lang.IObj x')
:cljs (satisfies? IWithMeta x'))
(vary-meta assoc :om-path path)))))))
@anmonteiro
Copy link

(defn path-meta
  ([x path]
   (path-meta x path nil))
  ([x path query]
   (letfn [(get-dispatch-key [prop]
             (cond-> prop
               (and (qutil/ident? prop)
                 (= (second prop) '_)) ((comp :dispatch-key expr->ast))))
           (strip-params [q]
             (cond-> q (seq? q) first))
           (descend-into-map-entry [k v idx]
             (path-meta
               v
               (conj path k)
               ;; TODO: check if `query` is a map which
               ;; happens for union queries. How do we
               ;; know which subquery to descend with?               
               (let [q  (if (vector? query)
                          (if (= query '[*])
                            (first query)
                            (let [query' (into [] (map strip-params) query)]
                              (or (some #{k} (map get-dispatch-key query'))
                                (zip/node (qutil/query-template query' [k]))))))]
                 (if (and (map? v) (map? q))
                   ;; If the value and the query is a map, it was a
                   ;; join that returned a single value. Use the join
                   ;; query specifically
                   (first (vals q))
                   q))))]
     (let [x' (cond->> x
                (map? x)
                (into {} (map-indexed
                           (fn [idx [k v]]
                             [k (descend-into-map-entry k v idx)])))

                (vector? x)
                (into [] (map-indexed
                           (fn [idx v]
                             (path-meta v
                                (conj path idx)
                                query)))))]
       (cond-> x'
         #?(:clj  (instance? clojure.lang.IObj x')
            :cljs (satisfies? IWithMeta x'))
         (vary-meta assoc :om-path path))))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment