Skip to content

Instantly share code, notes, and snippets.

@mike-thompson-day8
Last active June 25, 2018 14:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mike-thompson-day8/76812d5452747bc79aac to your computer and use it in GitHub Desktop.
Save mike-thompson-day8/76812d5452747bc79aac to your computer and use it in GitHub Desktop.
Middleware Which Acts Like A reverse reaction
(defn on-changes
"Middleware factory which acts a bit like \"reaction\" (but it flows into db , rather than out)
It observes N inputs (paths into db) and if any of them change (as a result of the
handler being run) then it runs 'f' to compute a new value, which is
then assoced into the given out=path within app-db.
Usage:
(defn my-f
[a-val b-val]
... some computation on a and b in here)
(on-changes my-f [:c] [:a] [:b])
"
[f out-path & in-paths]
(fn on-changed-middleware
[handler]
(fn on-changed-handler
[db v]
(let [ ;; run the handler, computing a new generation of db
new-db (handler db v)
;; work out if any "inputs" have changed
new-ins (map #(get-in new-db %) in-paths)
old-ins (map #(get-in db %) in-paths)
changed-ins? (some false? (map identical? new-ins old-ins))]
;; if one of the inputs has changed, then run 'f'
(if changed-ins?
(assoc-in new-db out-path (apply f new-ins))
new-db)))))
;; Testing
(defn my-f
[a-val b-val]
(+ a-val b-val))
;; this event handler just updates path [:a] with a new value
(defn handler
[db v]
(assoc db :a 0))
(def on-change-mid-ware (on-changes my-f [:c] [:a] [:b])) ;; instead of my-f, could just supply '+'
;; a handler - middware wrapping the original handler
(def mwh (on-change-mid-ware handler))
(mwh {:a 0 :b 2} nil)
;; => {:a 0 :b 2} ;; no change
(mwh {:a 4 :b 2} nil)
;; => {:c 2, :a 0, :b 2}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment