Back
build (clj)
(source)function
(build config keys f)
(build config keys f assertf)
(build config keys f assertf resolvef)
Apply a function f to each key value pair in a configuration map. Keys are
traversed in dependency order, and any references in the value expanded. The
function should take two arguments, a key and value, and return a new value.
An optional fourth argument, assertf, may be supplied to provide an assertion
check on the system, key and expanded value.
Examples
integrant
(ns integrant.core-test
(:require #?(:clj [clojure.test :refer [are deftest is testing]]
:cljs [cljs.test :refer-macros [are deftest is testing]])
[integrant.core :as ig]
[weavejester.dependency :as dep]))
(testing "with failing asserts"
(is (thrown-with-msg?
#?(:clj clojure.lang.ExceptionInfo :cljs cljs.core.ExceptionInfo)
(re-pattern (str "Assertion failed on key " ::n
" when building system"))
(ig/init {::n (ig/ref ::k), ::k 1.1}))))
(testing "with failing composite specs"
(is (thrown-with-msg?
#?(:clj clojure.lang.ExceptionInfo :cljs cljs.core.ExceptionInfo)
(re-pattern (str "Assertion failed on key \\[" ::n " " ::nnn "\\] "
"when building system"))
(ig/init {[::n ::nnn] 1.1})))))
(defn build-log [config]
(let [log (atom [])]
[(ig/build config (keys config)
(fn [k v] (last (swap! log conj [:build k v]))))
@log]))
(deftest build-test
(is (= [{::a [:build ::a [:build ::b 1]]
::b [:build ::b 1]}
[[:build ::b 1]
[:build ::a [:build ::b 1]]]]
(build-log {::a (ig/ref ::b)
::b 1}))))
(deftest run-test
(let [config {::a (ig/ref ::b), ::b 1}
[system _] (build-log config)]
(is (= [nil
[[:test ::b [:build ::b 1]]
[:test ::a [:build ::a [:build ::b 1]]]]]
(test-log ig/run! system)))
(is (= [nil
[[:test ::a [:build ::a [:build ::b 1]]]
[:test ::b [:build ::b 1]]]]
(test-log ig/reverse-run! system)))))
(deftest wrapped-exception-test
(testing "exception when building"
(let [ex (try (ig/init {::a 1, ::error-init (ig/ref ::a)}) nil
(catch #?(:clj Throwable :cljs :default) t t))]
(is (some? ex))
(is (= (#?(:clj .getMessage :cljs ex-message) ex)
(str "Error on key " ::error-init " when building system")))
(is (= (ex-data ex)
{:reason ::ig/build-threw-exception
:system {::a [1]}
:function ig/init-key
:key ::error-init
:value [1]}))
(let [cause (#?(:clj .getCause :cljs ex-cause) ex)]
(is (some? cause))
(is (= (#?(:clj .getMessage :cljs ex-message) cause) "Testing"))
(is (= (ex-data cause) {:reason ::test})))))
Zetawar/zetawar
(ns zetawar.system.game-views
(:require
[integrant.core :as ig]
[posh.reagent :as posh]
[tongue.core :as tongue]
[zetawar.data :as data]
[zetawar.logging :as log]
[zetawar.router :as router]))
;; TODO: start Reagent components when running in the browser
(defmethod ig/init-key :zetawar.system/game-views [_ opts]
(let [{:keys [datascript router locale]} opts
{:keys [conn]} datascript
{:keys [ev-chan]} router
dispatch #(router/dispatch ev-chan %)
translate (-> data/dicts
tongue/build-translate
(partial locale))]
(posh/posh! conn)
{:conn conn
:dispatch dispatch
:translate translate}))
(defmethod ig/resume-key :zetawar.system/game-views [_ opts old-opts old-impl]
(let [{:keys [datascript router locale]} opts
{:keys [conn]} datascript
{:keys [ev-chan]} router
old-conn (get-in old-opts [:datascript :conn])
dispatch #(router/dispatch ev-chan %)
translate (-> data/dicts
tongue/build-translate
(partial locale))]
(when-not (= conn old-conn)
(posh/posh! conn))
{:conn conn
:dispatch dispatch
:translate translate}))