summaryrefslogtreecommitdiff
path: root/compojure-3.2/src/compojure/validation.clj
blob: 35e8e3225c1e361b23c3d268127316d688805033 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
;; Copyright (c) James Reeves. All rights reserved.
;; The use and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
;; can be found in the file epl-v10.html at the root of this distribution. By
;; using this software in any fashion, you are agreeing to be bound by the
;; terms of this license. You must not remove this notice, or any other, from
;; this software.

(ns compojure.validation
  "Functions for validating form parameters."
  (:use compojure.control
        compojure.html.form-helpers
        compojure.html.page-helpers
        clojure.contrib.def))

(defvar *errors* {}
  "Var containing validation errors.")

(load "validation/predicates")

(defn validate 
  "Validate a single parameter, or group of parameters, using a predicate. If
  the predicate fails, a validation error is returned. For a single parameter,
  use the following form:
    (validate params name pred message)
  This will use the value of (pred (params name)) to determine if the parameter
  is valid. For multiple parameters:
    (validate params pred message)
  This will use the value of (pred params) to determine validity."
  ([params pred message]
    (if (pred params)
      {}
      {nil [message]}))
  ([params name pred message]
    (if (pred (params name))
      {}
      {name [message]})))

(defn merge-errors
  "Merge a set of validation errors into a single hash map."
  [& results]
  (apply merge-with #(into [] (concat %1 %2)) results))

(defn validation
  "Convinience function to perform a series of validations on a map of params.
  Takes a set of params and a collection of argument vectors for the validate
  function:
  e.g. (validation params
         [name pred message]
         [pred message])
  Is the same as:
       (merge-errors
         (validate params name pred message)
         (validate params pred message))"
  [params & validations]
  (apply merge-errors
    (map #(apply validate params %) validations)))

(defn validation-errors?
  "True if there are errors in the var *errors*."
  []
  (seq *errors*))

(defmacro with-validation
  "Binds *errors* to (validation-fn *params*)."
  [validation-fn & body]
  `(binding [*errors* (~validation-fn *params*)]
    ~@body))

(defmacro with-validated-params
  "Equivalent to (with-params params (with-validation validation-fn))."
  [params validation-fn & body]
  `(with-params ~params
     (with-validation ~validation-fn
       ~@body)))

(defn error-summary
  "Returns a summary of the errors on the form in HTML."
  []
  (unordered-list (apply concat (vals *errors*))))

(defn error-class
  "Decorator function that marks an input field with an error class if the
  parameter has errors."
  [func]
  (fn [name & args]
    (let [errors (*errors* name)
          result (apply func name args)]
      (if (seq errors)
        [:div.error result]
        result))))