如何指定地图中的两个键与Clojure.Spec应具有相同的值?

时间:2018-01-23 20:14:33

标签: clojure clojurescript clojure.spec

说一个最小的例子,我有一张包含以下字段的地图。

{:name
 :password
 :confirm-password}

我已经为这个形状编写了以下规格。

(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])

我如何编写::confirm-password规范来检查两个值是否相等?即我需要访问其他字段(密码)才能访问它。

我尝试过的一件事就是在注册表单上编写规范来访问密钥以确保它们是相同的并且那种工作但但问题是我失去了路径特性。基本上,生成的规范/问题指向注册表单,而不是我理想的::confirm-password

1 个答案:

答案 0 :(得分:2)

您可以使用s/and规范s/keys另一个谓词来检查两个密钥之间的相等性。值:

(s/def ::sign-up-form
  (s/and
    (s/keys :req-un [::name
                     ::password
                     ::confirm-password])
    #(= (:password %) (:confirm-password %))))

此匿名函数谓词接收s/keys规范的整个一致映射输出。

(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 %))