Skip to content

Commit 36dc045

Browse files
committed
correct 'reset!' and 'add-watch' to act like atoms. Added related tests.
1 parent 6c0cf5d commit 36dc045

File tree

2 files changed

+83
-10
lines changed

2 files changed

+83
-10
lines changed

Diff for: src/reagent/cursor.cljs

+28-10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
;; Implementation based on RAtom by delegation
1616

17+
1718
(deftype RCursor [path ratom]
1819
IAtom
1920

@@ -26,7 +27,8 @@
2627

2728
IReset
2829
(-reset! [a new-value]
29-
(swap! ratom assoc-in path new-value))
30+
(-> (swap! ratom assoc-in path new-value)
31+
(get-in path)))
3032

3133
ISwap
3234
(-swap! [a f]
@@ -65,24 +67,40 @@
6567
(-notify-watches [this oldval newval]
6668
(-notify-watches ratom oldval newval))
6769
(-add-watch [this key f]
68-
(-add-watch ratom key f))
70+
(-add-watch ratom [path key]
71+
(fn [k r o n]
72+
(f key
73+
this
74+
(get-in o path)
75+
(get-in n path)))))
6976
(-remove-watch [this key]
70-
(-remove-watch ratom key))
77+
(-remove-watch ratom [path key]))
7178

7279
IHash
7380
(-hash [this] (goog/getUid this)))
7481

7582
;; RCursor
7683

7784
(defn cursor
78-
"Provide a cursor into a Reagent atom.
85+
"Provide a cursor into an atom.
86+
87+
When called with a single argument, return a function that will
88+
create a cursor given an atom.
7989
80-
Behaves like a Reagent atom but focuses updates and derefs to
81-
the specified path within the wrapped Reagent atom. e.g.,
90+
Behaves like an atom but focuses updates and derefs to the specified
91+
path within the wrapped atom. e.g.,
8292
(let [c (cursor [:nested :content] ra)]
83-
... @c ;; equivalent to (get-in @ra [:nested :content])
84-
... (reset! c 42) ;; equivalent to (swap! ra assoc-in [:nested :content] 42)
85-
... (swap! c inc) ;; equivalence to (swap! ra update-in [:nested :content] inc)
86-
)"
93+
... @c ;; equivalent to (get-in @ra [:nested :content])
94+
... (reset! c 42) ;; equivalent to (swap! ra assoc-in [:nested :content] 42)
95+
... (swap! c inc) ;; equivalence to (swap! ra update-in [:nested :content] inc)
96+
)"
8797
([path] (fn [ra] (cursor path ra)))
8898
([path ra] (RCursor. path ra)))
99+
100+
101+
(defn cur
102+
"Create a cursor.
103+
104+
Behaves like a normal atom for the value at the specified path."
105+
[a path]
106+
(RCursor. path a))

Diff for: test/cursor_impl.cljs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
;; copyright (c) 2014 Frozenlock
2+
(ns cursor-impl
3+
(:require-macros [cemerick.cljs.test
4+
:refer (is deftest with-test run-tests testing)])
5+
(:require [cemerick.cljs.test :as t]
6+
[reagent.cursor :as c]))
7+
8+
;; Here we test if the cursors act as a normal atom
9+
10+
(deftest values
11+
(let [test-atom (atom {:a {:b {:c {:d 1}}}})
12+
test-cursor (c/cur test-atom [:a :b :c :d])]
13+
14+
;; get the initial values
15+
(is (= (get-in @test-atom [:a :b :c :d])
16+
@test-cursor))
17+
18+
;; now we update the cursor with a reset
19+
(reset! test-cursor 2)
20+
(is (= @test-cursor 2))
21+
(is (= (get-in @test-atom [:a :b :c :d]) 2))
22+
23+
;; swap
24+
(reset! test-cursor {}) ;; empty map
25+
(swap! test-cursor assoc :z 3)
26+
(is (= @test-cursor {:z 3}))
27+
(is (= (get-in @test-atom [:a :b :c :d])
28+
{:z 3}))))
29+
30+
31+
(deftest atom-behaviors
32+
(let [test-atom (atom {:a {:b {:c {:d 1}}}})
33+
test-cursor (c/cur test-atom [:a :b :c :d])
34+
witness (atom nil)]
35+
;; per the description, reset! should return the new values
36+
(is (= {}
37+
(reset! test-cursor {})))
38+
39+
;; per the description, swap! should return the new values
40+
(is (= {:z [1 2 3]}
41+
(swap! test-cursor assoc :z [1 2 3])))
42+
43+
;; watches should behave like with a normal atom
44+
(reset! test-cursor "old")
45+
(add-watch test-cursor :w #(reset! witness {:key %1 :ref %2 :old %3 :new %4}))
46+
(reset! test-cursor "new") ;; this should trigger the watch function
47+
(is (= (:key @witness) :w))
48+
(is (= (:ref @witness) test-cursor))
49+
(is (= (:old @witness) "old"))
50+
(is (= (:new @witness) "new"))
51+
;; can we remove the watch?
52+
(remove-watch test-cursor :w)
53+
(reset! test-cursor "removed")
54+
(is (= (:new @witness) "new")) ;; shouldn't have changed
55+
))

0 commit comments

Comments
 (0)