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#)))))))) |