malli

https://github.com/metosin/malli :malli:
escherize 2021-06-23T21:31:13.205600Z

I’d like to attach error messages to specific parts of my schema. So far I have the following working, but I’m not sure if it’s the best implementation.

(def MySchema
  [:map
   [:something/one {:error/message "one"} int?]
   [:something/two {:error/message "2"} int?]
   [:something/three {:error/message "three"} int?]
   [:something/four {:error/message "four"} int?]])

(validate MySchema {})
;; => #:something{:one ["one"], :two ["2"], :three ["three"], :four ["four"]}

escherize 2021-06-23T21:33:30.207100Z

I am using the following to get this working:

(defn find-error-message [schema k]
  (let [value (atom nil)]
    (walk/postwalk
     (fn [x]
       (when (and x (vector? x) (= (first x) k) (map? (second x)))
         (reset! value (second x)))
       x)
     schema)
    (:error/message @value)))

;; then, in humanize:

(me/humanize ...
 {:errors
  (assoc me/default-errors

   :malli.core/missing-key
   {:error/fn (fn [{:keys [in]} _]
                (or
                 (find-error-message schema (last in)) ;; is (last in) reliable here?
                 (str "Missing key: '"(last in)"'")))})})

escherize 2021-06-23T21:38:09.208500Z

I’m not sure if using (last in) in the :error/fn is reliable though.