Last active
September 1, 2015 06:49
-
-
Save jstaffans/fd8e6683cf9cb24ebdde to your computer and use it in GitHub Desktop.
Nested data sources with muse
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Trying to traverse an AST whose root is a list | |
(defrecord ParentDS [] | |
muse/DataSource | |
(fetch [_] | |
(async/go [{:id 1 :name "Parent 1"} {:id 2 :name "Parent 2"}])) | |
muse/LabeledSource | |
(resource-id [_] | |
:some-label)) | |
(defrecord ChildDS [parent] | |
muse/DataSource | |
(fetch [_] | |
(async/go | |
{:belongs-to (:name parent)})) | |
muse/LabeledSource | |
(resource-id [_] | |
parent)) | |
(muse/run!! (muse/traverse | |
(fn [parent] | |
(muse/fmap | |
(fn [child] (assoc parent :child child)) | |
(ChildDS. parent))) | |
(ParentDS.))) | |
=> [{:id 1, :name "Parent 1", :child #muse.core.MuseDone{:value {:belongs-to "Parent 1"}}} {:id 2, :name "Parent 2", :child #muse.core.MuseDone{:value {:belongs-to "Parent 2"}}}] | |
;; So far so good. But how do I extend it beyond "(muse/value child)", ie for grandchildren? | |
(defrecord GrandchildDS [parent] | |
muse/DataSource | |
(fetch [_] | |
(async/go | |
{:grandchild-of (:belongs-to parent)})) | |
muse/LabeledSource | |
(resource-id [_] | |
parent)) | |
(muse/run!! | |
(muse/traverse | |
(fn [parent] ;; {:id 1 :name "Parent 1"} | |
(muse/flat-map | |
(fn [child] ;; {:belongs-to "Parent 1"} | |
(muse/fmap | |
(fn [grandchild] ;; {:grandchild-of "Parent 1"} | |
;; all values are already evaluated here | |
(assoc parent :child (muse/value (assoc child :grandchild grandchild)))) | |
(GrandchildDS. child))) | |
(ChildDS. parent))) | |
(ParentDS.))) | |
=> [{:id 1, :name "Parent 1", :child {:belongs-to "Parent 1", :grandchild {:grandchild-of "Parent 1"}}} {:id 2, :name "Parent 2", :child {:belongs-to "Parent 2", :grandchild {:grandchild-of "Parent 2"}}} | |
;; 1. assoc happens only at end, when all values are known. | |
;; 2. muse/flat-map tells muse we need more data to build a value. | |
;; muse/value is a wrapper for data ready to be used, so the above is equivalent to: | |
(muse/run!! | |
(muse/traverse | |
(fn [parent] ;; {:id 1 :name "Parent 1"} | |
(muse/flat-map | |
(fn [child] ;; {:belongs-to "Parent 1"} | |
(muse/flat-map | |
(fn [grandchild] ;; {:grandchild-of "Parent 1"} | |
;; all values are already evaluated here | |
(muse/value (assoc parent :child (assoc child :grandchild grandchild)))) | |
(GrandchildDS. child))) | |
(ChildDS. parent))) | |
(ParentDS.))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment