Skip to content

Instantly share code, notes, and snippets.

@williballenthin
Created January 30, 2017 20:32
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 williballenthin/267be361bb8dd0fe893f61e16425e036 to your computer and use it in GitHub Desktop.
Save williballenthin/267be361bb8dd0fe893f61e16425e036 to your computer and use it in GitHub Desktop.
(def tests [{:name "one top level prop"
:model {:top-level-prop "A"}
:query [:top-level-prop]
:expected {:top-level-prop "A"}}
{:name "pluck one top level prop"
:model {:top-level-prop "A" :other-prop "B"}
;; even though there are two props at the top level,
;; we are only asking for one.
:query [:top-level-prop]
:expected {:top-level-prop "A"}}
{:name "pluck two top level props"
:model {:top-level-prop "A" :other-prop "B" :prop-c "C"}
;; now we ask for two of the three props.
:query [:top-level-prop :other-prop]
:expected {:top-level-prop "A" :other-prop "B"}}
{:name "pluck top level vector"
:model {:top-level-prop ["A" "B" "C"] :other-prop "B"}
;; now we ask for two of the three props.
:query [:top-level-prop]
:expected {:top-level-prop ["A" "B" "C"]}}
{:name "subselect item from vector"
:model {:top-level-prop [{:a "a" :b "b"} {:a "AAA" :b "BBB"}] :other-prop "B"}
;; here we have a vector of complex maps.
;; select only the :a prop from each map in the vector.
:query [{:top-level-prop [:a]}]
:expected {:top-level-prop [{:a "a"} {:a "AAA"}]}}
{:name "subselect items from vector"
:model {:top-level-prop [{:a "a" :b "b" :c "c"} {:a "AAA" :b "BBB" :c "CCC"}] :other-prop "B"}
;; here we have a vector of complex maps.
;; select only the :a prop from each map in the vector.
:query [{:top-level-prop [:a :b]}]
:expected {:top-level-prop [{:a "a" :b "b"} {:a "AAA" :b "BBB"}]}}
{:name "nested subselect"
:model {:top-level-prop [{:a [{:aa "a" :bb "b"}
{:aa "aa" :bb "bb"}]
:b "Z"}
{:a [{:aa "A" :bb "B"}
{:aa "AA" :bb "BB"}]
:b "Z"}]
:other-prop "Z"}
;; here we want to sub-select an already sub-selected item.
;; we want to get all the {:a {:aa}} props, and none of the :b or :bb props.
:query [{:top-level-prop [{:a [:aa]}]}]
:expected {:top-level-prop [{:a [{:aa "a"}
{:aa "aa"}]}
{:a [{:aa "A"}
{:aa "AA"}]}]}}
{:name "simple by iden"
:model {:things/by-iden {"abc" "foo", "def" "bar"}}
;; note that we use double-[
;; the first level is because the query is a list of things.
;; the second level is the ident [:things/by-iden "abc"]
:query [[:things/by-iden "abc"]]
:expected {[:things/by-iden "abc"] "foo"}}
{:name "by ident and join some props"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c "cc"}, "def" "bar"}}
;; note we use a { here to deref.
;; this means to sub-select a portion of the results.
;; so, we get the thing from [:things/by-iden "abc"]
;; and then select only the :a and :b props.
:query [{[:things/by-iden "abc"] [:a :b]}]
:expected {[:things/by-iden "abc"] {:a "aa" :b "bb"}}}
{:name "by ident and join one prop"
:model {:things/by-iden {"abc" {:a "aa" :b "bb"}, "def" "bar"}}
:query [{[:things/by-iden "abc"] [:a]}]
:expected {[:things/by-iden "abc"] {:a "aa"}}}
{:name "by ident with complex key"
:model {:things/by-iden {[1 2] {:a "aa" :b "bb"}, "def" "bar"}}
:query [{[:things/by-iden [1 2]] [:a]}]
:expected {[:things/by-iden [1 2]] {:a "aa"}}}
{:name "don't do this"
:model {:things/by-iden {"abc" {:a "aa" :b "bb"}, "def" "bar"}}
;; if you want to sub-select (join) some portion of the results,
;; don't do this!
;; this asks for the thing [:things/by-iden "abc"], and also
;; the thing [:a] (whatever that is).
;; the example above is the correct syntax.
:query [[:things/by-iden "abc"] [:a]]
:expected {[:things/by-iden "abc"] {:a "aa" :b "bb"}}}
{:name "by ident, don't yet nested join"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" "bar"}}
;; our item [:things/by-iden "abc"] now contains a reference
;; to [:things/by-iden "def"], but it doesn't resolve this item.
;; the reference remains as-is.
:query [[:things/by-iden "abc"]]
:expected {[:things/by-iden "abc"] {:a "aa" :b "bb" :c [:things/by-iden "def"]}}}
{:name "by ident, direct join, no nested join"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" "bar"}}
;; we can join some of the immediate props (:a and :c), but don't yet
;; follow the link that :c contains.
:query [{[:things/by-iden "abc"] [:a :c]}]
:expected {[:things/by-iden "abc"] {:a "aa" :c [:things/by-iden "def"]}}}
{:name "by ident, nested join"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" {:d "bar" :e "baz"}}}
;; now, we want to follow the link in :c.
;; we use join syntax ( { ), with the key being the prop name
;; of [:things/by-iden "abc"] that contains the link.
;; of course, maps must have an even number of entries, so the value
;; is the list of things we want from the target item.
:query [{[:things/by-iden "abc"] [:a {:c [:d]}]}]
:expected {[:things/by-iden "abc"] {:a "aa" :c {:d "bar"}}}}
{:name "by ident, nested join, two props"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" {:d "bar" :e "baz"}}}
;; get two things from the linked item (:d and :e).
:query [{[:things/by-iden "abc"] [:a {:c [:d :e]}]}]
:expected {[:things/by-iden "abc"] {:a "aa" :c {:d "bar" :e "baz"}}}}
{:name "by ident, nested join, all props"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" {:d "bar" :e "baz"}}}
;; use the special term '[*] that denotes "fetch the entire item".
:query [{[:things/by-iden "abc"] [:a {:c '[*]}]}]
:expected {[:things/by-iden "abc"] {:a "aa" :c {:d "bar" :e "baz"}}}}
{:name "by ident, nested join, all props, with dups"
:disabled "not supported by om/db->tree"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" {:d "bar" :e "baz"}}}
;; this syntax is not supported by om/db->tree
;; the * must be found in exactly '[*]
:query [{[:things/by-iden "abc"] [:a {:c ['* :d]}]}]
:expected {[:things/by-iden "abc"] {:a "aa" :c {:d "bar" :e "baz"}}}}
{:name "by ident, all props, with link"
:model {:things/by-iden {"abc" {:a "aa" :b "bb" :c [:things/by-iden "def"],}
"def" {:d "bar" :e "baz"}}}
;; although we are fetching the entire item, we don't expect the link
;; to be resolved.
:query [{[:things/by-iden "abc"] '[*]}]
:expected {[:things/by-iden "abc"] {:a "aa" :b "bb" :c [:things/by-iden "def"]}}}
{:name "list of links"
:model {:things/by-iden {"abc" {:a "aa" :b "bb"}
"def" {:a "AA" :b "AA"}}
:the-things [[:things/by-iden "abc"]
[:things/by-iden "def"]]}
:query [:the-things]
:expected {:the-things [[:things/by-iden "abc"]
[:things/by-iden "def"]]}}
{:name "join list of links"
:model {:things/by-iden {"abc" {:a "aa" :b "bb"}
"def" {:a "AA" :b "BB"}}
:the-things [[:things/by-iden "abc"]
[:things/by-iden "def"]]}
;; here we have a list of links to other things.
;; we want to traverse into those things.
:query [{:the-things [:a :b]}]
:expected {:the-things [{:a "aa" :b "bb"}
{:a "AA" :b "BB"}]}}
{:name "join list of links with star"
:model {:things/by-iden {"abc" {:a "aa" :b "bb"}
"def" {:a "AA" :b "BB"}}
:the-things [[:things/by-iden "abc"]
[:things/by-iden "def"]]}
;; here we have a list of links to other things.
;; we want to traverse into those things.
:query [{:the-things '[*]}]
:expected {:the-things [{:a "aa" :b "bb"}
{:a "AA" :b "BB"}]}}
{:name "missing iden"
:model {:things/by-iden {"abc" "foo", "def" "bar"}}
;; note that we use double-[
;; the first level is because the query is a list of things.
;; the second level is the ident [:things/by-iden "abc"]
:query [[:things/by-iden "xyz"]]
:expected {}
:missing-idents #{[:things/by-iden "xyz"]}}
{:name "union"
:via "https://github.com/omcljs/om/wiki/Queries-With-Unions"
:model {:dashboard/items
[[:dashboard/post 0]
[:dashboard/photo 1]
[:dashboard/post 2]
[:dashboard/graphic 3]
[:dashboard/post 4]],
:dashboard/post
{0
{:id 0,
:type :dashboard/post,
:title "A Post!",
:author "Laura Smith",
:content "Lorem ipsum dolor sit amet, quem atomorum te quo",
:favorites 0},
2
{:id 2,
:type :dashboard/post,
:title "Another Post!",
:author "Jim Jacobs",
:content "Lorem ipsum dolor sit amet, quem atomorum te quo",
:favorites 0},
4
{:id 4,
:type :dashboard/post,
:title "Yet Another Post!",
:author "May Fields",
:content "Lorem ipsum dolor sit amet, quem atomorum te quo",
:favorites 0}},
:dashboard/photo
{1
{:id 1,
:type :dashboard/photo,
:title "A Photo!",
:image "photo.jpg",
:caption "Lorem ipsum",
:favorites 0}},
:dashboard/graphic
{3
{:id 3,
:type :dashboard/graphic,
:title "Charts and Stufff!",
:image "chart.jpg",
:favorites 0}}}
;; :dashboard/items is a list that contains idents of different types.
;; we use a union query to map the ident type to the data we want for some ident type.
;; so, if the ident type is :dashboard/post, then we want six props, including :content.
;; but not including :image.
:query [{:dashboard/items
{:dashboard/post [:id :type :title :author :content :favorites],
:dashboard/photo [:id :type :title :image :caption :favorites],
:dashboard/graphic [:id :type :title :image :favorites]}}]
:expected {:dashboard/items
[{:id 0,
:type :dashboard/post,
:title "A Post!",
:author "Laura Smith",
:content "Lorem ipsum dolor sit amet, quem atomorum te quo",
:favorites 0}
{:id 1,
:type :dashboard/photo,
:title "A Photo!",
:image "photo.jpg",
:caption "Lorem ipsum",
:favorites 0}
{:id 2,
:type :dashboard/post,
:title "Another Post!",
:author "Jim Jacobs",
:content "Lorem ipsum dolor sit amet, quem atomorum te quo",
:favorites 0}
{:id 3,
:type :dashboard/graphic,
:title "Charts and Stufff!",
:image "chart.jpg",
:favorites 0}
{:id 4,
:type :dashboard/post,
:title "Yet Another Post!",
:author "May Fields",
:content "Lorem ipsum dolor sit amet, quem atomorum te quo",
:favorites 0}]}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment