I've been using theclavier library for input validation, it works nicely but we could make it a bit more terse.
Let's say you are building many HTML forms. Doing one all manually is OK-ish, not two. You could usecl-forms (I didn't, I'm building a layer to get a form from Mito objects. If you didn't see where I'm doing it look better or stay tuned ;) ) You could do things semi-manually and use Clavier for input validation. It works like this.
Define a list of validators for your fields:
(defmethodvalidators((obj(eql'book)))(dict'isbn(list;; other validator here…(clavier:len:min10:max13;; :message works with clavier's commit of <2024-02-27>;; :message "an ISBN must be between 10 and 13 characters long"))'title(clavier:~="test""this title is too common, please change it!")))
You can compose them with boolean logic:
(defparameter*validator*(clavier:||(clavier:blank)(clavier:&&(clavier:is-a-string)(clavier:len:min10)))"Allow a blank value. When non blank, validate.")
This validator allows an input to be an empty string, but if it isn't, it validates it.
(funcall*validator*"");; =>TNIL(funcall*validator*"asdf");; =>NIL"Length of \"asdf\" is less than 10"
For one, I want a shorter construct for this common need.My PR was rejected so here it is.
Use a:allow-blank
keyword:
(defmethodvalidators((obj(eql'book)))(dict'isbn(list:allow-blank(clavier:len:min10:max13…
and write avalidate-all
function:
(defunvalidate-all(validatorsobject)"Run all validators in turn. Return two values: the status (boolean), and a list of messages. Allow a keyword validator: :allow-blank. Accepts a blank value. If not blank, validate.";; I wanted this to be part of clavier, but well.;; https://github.com/mmontone/clavier/pull/10(let((messagesnil)(validt))(loopforvalidatorinvalidatorsif(and(eql:allow-blankvalidator)(str:blankpobject))returntelsedo(unless(symbolpvalidator)(multiple-value-bind(statusmessage)(clavier:validatevalidatorobject:error-pnil)(unlessstatus(setfvalidnil))(whenmessage(pushmessagemessages)))))(valuesvalid(reverse(uiop:ensure-listmessages)))))
This could be made better for a library API maybe? Anyways it works for now©.
See also that Clavier has a "validator-collection" thing, but not shown in the README, and is again too verbose in comparison to a simple list, IMO.
that's it, see ya next time.
Appendix: validators list:
This is the list of available validator classes and their shortcut function:
- equal-to-validator
(==)
- not-equal-to-validator
(~=)
- blank-validator
(blank)
- not-blank-validator
(not-blank)
- true-validator
(is-true)
- false-validator
(is-false)
- type-validator
(is-a type)
- string-validator
(is-a-string)
- boolean-validator
(is-a-boolean)
- integer-validator
(is-an-integer)
- symbol-validator
(is-a-symbol)
- keyword-validator
(is-a-keyword)
- list-validator
(is-a-list)
- function-validator
(fn function message)
- email-validator
(valid-email)
- regex-validator
(matches-regex)
- url-validator
(valid-url)
- datetime-validator
(valid-datetime)
- pathname-validator
(valid-pathname)
- not-validator
(~ validator)
- and-validator
(&& validator1 validator2)
- or-validator
(|| validator1 validator2)
- one-of-validator
(one-of options)
- less-than-validator
(less-than number)
- greater-than-validator
(greater-than number)
- length-validator
(len)
:allow-blank
(not merged, only in my fork)
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse