Hi! This is definitely a novice question, but I’ve struggled for a day or so trying to figure out the best way to use spec in my re-frame application. My problems stem from not grokking spec I think.
I’m using my app db to store form information under a :form key. Forms are stored by form-id.
In each field the “error” is set based on a spec that gets checked on each edit:
(s/def ::id (s/and string? #(> (count %) 0)) )
(s/def ::team (s/and string? #(> (count %) 0)) )
(s/def ::nickname (s/and string? #(> (count %) 0)))
(s/def ::password (s/and string? #(> (count %) 7)) )
(Lengths are set to zero but will change)
But I also want to define a spec for the form as a whole, so I can pass the “signup” form above to (s/valid?). But I can’t figure out how to define the structure above, where signup has four keys, each of which have the same structure
in :signup :team for example, I want to say signup has a map that requires a :team key, and the team key is a map that has a :value key that is defined by ::team in the snippet pasted above
I can’t define a ::value spec to include in (s/keys) for :team - because what :value is is different for each sibling key in :signup
I’m not sure that I understand 100% but you might need to put each :value key into a different namespace so that they can be a distinct spec e.g :foo/value, :bar/value. You could also check out multi-spec for multimethod like dispatch on the submaps
spec is primarily designed to associate semantic specs with namespaced keys, so by using :value in each of these places (instead of :id/value or whatever), you are outside the sweet spot
you can do this with s/keys and :req-un for unqualified keys though, but you'll need to match up the name parts of the specs
(s/def :team/value ::team) ;; same for the others
(s/def :team/team (s/keys :req-un [::team/value])) ;; same for the others
(s/def ::signup (s/keys :req-un [:team/team ..etc..]))
as I said, this is outside the expected pattern so it's more work for sure
Thanks Alex. What is the preferred way to satisfy the goal I have here, which is to independently validate the form contents and the form data as a whole? Is the correct answer to my confusion “read more”? 🙂
the preferred way is to have namespaced attributes with one meaning