Skip to content

Commit

Permalink
Merge pull request #46 from michalmarczyk/validate-nested
Browse files Browse the repository at this point in the history
Add validate-nested
  • Loading branch information
michaelklishin committed Mar 2, 2016
2 parents 346f99e + 15b1a8b commit 1ac862e
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
34 changes: 33 additions & 1 deletion src/validateur/validation.cljc
Expand Up @@ -461,7 +461,6 @@
[true {}]
[false {attr #{message}}])))))


(defn nest
"Takes an attribute (either a single key or a vector of keys) and a
validation set and prefixes the keys in the validation set's
Expand Down Expand Up @@ -497,6 +496,39 @@
[(subvec k attrcount (count k)) messages])
(into {}))))

(defn validate-nested
"Returns a function that, when given a map, will validate that the
value of at key attr in that map passes validation using the given
validator (a function as returned by validation-set).
Accepted options:
:message (default: \"is invalid\"): an error message for invalid values
:message-fn (default:nil): function to retrieve message with signature (fn [map])
Example:
(require '[validateur.validation :refer :all])
(def foo-validator (validation-set (presence-of :foo)))
(validation-set (validate-nested :bar foo-validator))"
[attr validator & {:keys [message message-fn]}]
(let [get-fn (if (vector? attr) get-in get)
validate-fn (if (or message message-fn)
(let [msg-fn (or message-fn (constantly message))]
(fn [m]
(reduce-kv (fn [out k v]
(assoc out k #{(msg-fn m)}))
{}
(validator m))))
validator)]
(fn [m]
(let [value (get-fn m attr)
result (validate-fn value)]
(if (seq result)
[false (nest attr result)]
[true {}])))))

(defn validate-with-predicate
"Returns a function that, when given a map, will validate that the predicate returns
Expand Down
61 changes: 61 additions & 0 deletions test/validateur/test/validation_test.cljc
Expand Up @@ -786,6 +786,67 @@
(vr/inclusion-of :status :in #{:active :inactive})))]
(is (= {} (v {:person {:name "Michał" :status :active}})))))

;;
;; validate-nested
;;

(deftest test-validate-nested-validation-fails
(let [person-v (vr/validation-set
(vr/presence-of :name)
(vr/format-of :name :format #"[A-Za-z]+"))
v (vr/validate-nested :person person-v)]
(is (= [false {[:person :name] #{"can't be blank"}}]
(v {})))
(is (= [false {[:person :name] #{"can't be blank"}}]
(v {:person {}})))
(is (= [false {[:person :name] #{"can't be blank"}}]
(v {:person {:name nil}})))
(is (= [false {[:person :name] #{"can't be blank"}}]
(v {:person {:name ""}})))
(is (= [false {[:person :name] #{"has incorrect format"}}]
(v {:person {:name "123"}})))))

(deftest test-validate-nested-validation-succeeds
(let [person-v (vr/validation-set
(vr/presence-of :name)
(vr/format-of :name :format #"[A-Za-z]+"))
v (vr/validate-nested :person person-v)]
(is (= [true {}]
(v {:person {:name "Michał"}})))))

(deftest test-validate-nested-validation-fails-with-custom-message
(let [person-v (vr/validation-set
(vr/presence-of :name)
(vr/format-of :name :format #"[A-Za-z]+"))
v (vr/validate-nested :person person-v :message "test")]
(is (= [false {[:person :name] #{"test"}}]
(v {})))
(is (= [false {[:person :name] #{"test"}}]
(v {:person {}})))
(is (= [false {[:person :name] #{"test"}}]
(v {:person {:name nil}})))
(is (= [false {[:person :name] #{"test"}}]
(v {:person {:name ""}})))
(is (= [false {[:person :name] #{"test"}}]
(v {:person {:name "123"}})))))

(deftest test-validate-nested-validation-fails-with-custom-message-fn
(let [person-v (vr/validation-set
(vr/presence-of :name)
(vr/format-of :name :format #"[A-Za-z]+"))
v (vr/validate-nested :person person-v
:message-fn (fn [m]
(str "test" (+ (count m) (count (:person m))))))]
(is (= [false {[:person :name] #{"test0"}}]
(v {})))
(is (= [false {[:person :name] #{"test0"}}]
(v {:person {}})))
(is (= [false {[:person :name] #{"test1"}}]
(v {:person {:name nil}})))
(is (= [false {[:person :name] #{"test1"}}]
(v {:person {:name ""}})))
(is (= [false {[:person :name] #{"test1"}}]
(v {:person {:name "123"}})))))

;;
;; Error Reporting
Expand Down

0 comments on commit 1ac862e

Please sign in to comment.