Say for a minimal example, I've got a map with the following fields.
{:name
:password
:confirm-password}
and I've written the following specs for this shape.
(s/def ::name string?)
;; password is a string and between 8 - 255 characters
(s/def ::password (s/and string? #(<= 8 (count %) 255))
;; How to write (s/def ::confirm-password)
(s/def ::sign-up-form (s/keys :req-un [::name
::password
::confirm-password])
How would I go about writing a ::confirm-password spec to check whether the two values are equal? i.e. I need access to that other field (password) to get to it.
One thing I tried was to write the spec on the sign-up-form to get access to the keys to make sure they were the same and that kind of works but the problem with that is I lose the path specificity. Basically the spec/problem that get's generated points towards the sign-up form rather than the ::confirm-password which I would like ideally.
You can s/and another predicate with your s/keys spec to check equality between the two keys' values:
(s/def ::sign-up-form
(s/and
(s/keys :req-un [::name
::password
::confirm-password])
#(= (:password %) (:confirm-password %))))
This anonymous function predicate receives the entire conformed map output of the s/keys spec.
(s/explain ::sign-up-form
{:name "Taylor"
:password "weak pass"
:confirm-password "weak pass!"})
;; val: {:name "Taylor", :password "weak pass", :confirm-password "weak pass!"}
;; fails spec: :sandbox.so/sign-up-form predicate:
;; (= (:password %) (:confirm-password %))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With