Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Vlad is an attempt at providing convenient and simple validations. Vlad is purely functional and makes no assumptions about your data. It can be used for validating html form data just as well as it can be used to validate your csv about cats.
Clojure Shell
tree: 91cb71dd0e

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
dev
script
src
test/vlad/test
.gitignore
README.md
project.clj

README.md

Vlad

Vlad is an attempt at providing convenient and simple validations. Vlad is purely functional. It makes no assumptions about your data. It can be used for validating html post data just as well as it can be used to validate your csv about cats.

Those coming from a Ruby on Rails background will be famliar with validations poluted with conditional statements and models poluted with virtual attributes. Vlad aims to avoid this mess.

To use Vlad add the following to your project.clj dependencies:

[vlad "1.1.0"]

API Docs: http://logaan.github.io/vlad/vlad.html

Basics

(ns vlad.test.readme
  (:require [vlad :refer :all]
            [midje.sweet :refer [fact]]))

(def validation
  (present [:age]))

(def invalid-data
  {:name "Logan Campbell"})

(fact (validate validation invalid-data)
      => [{:type :vlad.validations/present
           :selector [:age]}])

Composition

Vlad lets you build complex validations through composition. join will return a validation that checks each of it's arguments. chain will stop checking once the first validation fails. This helps avoid overwhelming your users with redundant error messages.

(def common
  (join (present [:name])
        (present [:email])))

(def password
  (chain (present [:password])
         (join (length-in 6 128 [:password])
               (matches #"[a-zA-Z]" [:password])
               (matches #"[0-9]" [:password]))
         (equals-field [:password] [:confirmation])))

(def signup
  (join common password))

(def update
  common)

(fact (validate signup {:name "Logan Campbell"})
      => '({:selector [:email],    :type :vlad.validations/present}
           {:selector [:password], :type :vlad.validations/present}))

Notice that only the :vlad.validations/present validation was shown for :password. Errors about length, patterns and confirmation are not shown until appropriate. In this case chain has also saved us from nil pointer errors as later validations are only run if earlier ones pass.

And of course all these validations could be run over any data. Whether you're pulling it in from a web service, a database or a csv file somewhere.

Translation

Vlad is an exercise in extreme simpicity. This means you can use validations in any number of ways. Because errors are not coupled to messages Vlad is well suited for localisation. Default english translations are provided for your convenience.

(def english-field-names
  {[:name]         "Full Name"
   [:email]        "Email Address"
   [:password]     "Password"
   [:confirmation] "Password Confirmation"})

(midje/fact
  (-> (validate signup {:password "!"})
      (assign-name english-field-names)
      (translate-errors english-translation))

  => {[:password] ["Password must be over 6 characters long."
                   "Password must match the pattern [a-zA-Z]."
                   "Password must match the pattern [0-9]."],
      [:email]    ["Email Address is required."],
      [:name]     ["Full Name is required."]})

(def chinese-field-names
  {[:name]         "姓名"
   [:email]        "邮箱"
   [:password]     "密码"
   [:confirmation] "确认密码"})

(defmulti chinese-translation :type)

(defmethod chinese-translation :vlad.validations/present
  [{:keys [name]}]
  (format "请输入%s" name))

; Other validation translations go here.

(midje/fact
  (-> (validate update {:name "Rich"})
      (assign-name chinese-field-names)
      (translate-errors chinese-translation))

  => {[:email] ["请输入邮箱"]})

Alternatives

There are 7 validation libraries up on Clojure Toolbox. I believe Vlad to be the simplest of the lot. It differs from most other's in the following ways:

  • Validations can be composed. Fail fast composition (chain in Vlad) is missing from all libraries I saw. This runs the risk of presenting your users with a page full of redundant errors.
  • Validations are not tied to any particular data type. They just need to implement the vlad.validation-types/Validation protocol. A default implementation has been made for clojure.lang.IFn.
  • Neither field names nor error messages are tied to validations. You can define your validation rules once and then translate them in many different ways. Or not at all if you choose.
  • Vlad is not tied to the web. It is suitable for more than just form data processing. It is also not tied to any web framework.

License

Copyright © 2012 Logan Campbell

Distributed under the Eclipse Public License, the same as Clojure.

Something went wrong with that request. Please try again.