Helper macros for defining Settings that can have multiple getter/setter implementations. The implementation that gets used is determined at runtime when the getter or setter is invoked by a dispatch function. This functionality was originally intended to facilitate separate EE and OSS versions of Settings, but rather than
restrict the impls to just See PR #16365 for more context. | (ns metabase.models.setting.multi-setting (:require [metabase.models.setting :as setting] [metabase.util.i18n :refer [tru]])) |
(set! *warn-on-reflection* true) | |
Determine the dispatch value for a multi-Setting defined by | (defmulti dispatch-multi-setting {:arglists '([setting-key])} keyword) |
Get the value of a multi-Setting defined by | (defmulti get-multi-setting {:arglists '([setting-key impl])} (fn [setting-key impl] [(keyword setting-key) (keyword impl)])) |
Update the value of a multi-Setting defined by | (defmulti set-multi-setting {:arglists '([setting-key impl new-value])} (fn [setting-key impl _] [(keyword setting-key) (keyword impl)])) |
Define a Setting that can have multiple getter/setter implementations. The implementation used is determined by
calling defsetting : define-multi-setting :: defn : defmulti | (defmacro define-multi-setting {:style/indent :defn} [setting-symbol doc dispatch-thunk & {:as options}] (let [setting-key (keyword setting-symbol) options (merge {:getter `(fn [] (get-multi-setting ~setting-key (dispatch-multi-setting ~setting-key))) :setter `(fn [new-value#] (set-multi-setting ~setting-key (dispatch-multi-setting ~setting-key) new-value#))} options)] `(do (let [dispatch-thunk# ~dispatch-thunk] (defmethod dispatch-multi-setting ~setting-key [~'_] (dispatch-thunk#))) (setting/defsetting ~setting-symbol ~doc ~@(mapcat identity options))))) |
Define a implementation for a Setting defined by define-multi-setting : define-multi-setting-impl :: defmulti : defmethod See | (defmacro define-multi-setting-impl [setting-symbol dispatch-value & {:keys [getter setter]}] (let [setting-key (keyword (name setting-symbol)) dispatch-value (keyword dispatch-value)] `(do ~(when getter `(let [getter# ~getter] (defmethod get-multi-setting [~setting-key ~dispatch-value] [~'_ ~'_] (getter#)))) ~(when setter (if (= setter :none) `(defmethod set-multi-setting [~setting-key ~dispatch-value] [~'_ ~'_ ~'_] (throw (UnsupportedOperationException. (tru "You cannot set {0}; it is a read-only setting." ~setting-key)))) `(let [setter# ~setter] (defmethod set-multi-setting [~setting-key ~dispatch-value] [~'_ ~'_ new-value#] (setter# new-value#)))))))) |