Howdy y'all, I'm wondering if it's possible to "bubble up" a spec error from s/every. Here's what I mean:
(s/def :nuzzle/title string?)
(s/def :nuzzle/rss? boolean?)
(s/def :nuzzle/page-entry (s/keys :req [:nuzzle/title] :opt [:nuzzle/rss?]))
(s/def :nuzzle/user-config
(s/and
(s/keys :req [:nuzzle/base-url])
(s/every (fn [[key _]] (or (keyword? key) (vector? key))))
(s/every (fn [[key val]] (or (not (vector? key))
(s/valid? :nuzzle/page-entry val))))))
(s/explain
:nuzzle/user-config
{:nuzzle/base-url ""
[:blog-posts :test-post] {:nuzzle/title 234 :nuzzle/rss? true}})
For every key-value pair in the config map where the key is a vector, I want to validate the associated value against a spec (in this case :nuzzle/page-entry). I'm using s/every because vector keys can be arbitrary but their values must conform to :nuzzle/page-entry.
The problem is that when a schema error occurs for a :nuzzle/page-entry (for example :nuzzle/title is not a string), I get an s/explain output like this:
[[:blog-posts :test-post] #:nuzzle{:title 234, :rss? true}] - failed: (fn [[key val]] (or (not (vector? key)) (valid? :nuzzle/page-entry val))) in: [1] spec: :nuzzle/user-config
Is there any way to refactor this to get a better error message about the specific problematic key-value pair (`:nuzzle/title 234`)?I don't know if this will help but you may find the techniques used in https://cognitect.com/blog/2017/1/3/spec-destructuring to be helpful here
that is, treating the map as a coll of an s/or of k/v tuple types (rather than as a map)
@alexmiller I will read up on this, thank you!