Awesome
✅ Pragma-Validators
A set of declarative validators for Pharo accessors, inspired by JSR-380 Java Bean Validation annotations.
🪄 Usage in a nutshell
- Make a class, declare several inst vars and generate their corresponsing accessors.
Object subclass: #RegistrationRequest
instanceVariableNames: 'username name password emails'
classVariableNames: ''
package: 'MyApplication-DataTransfer'
- Annotate the accessors with desired validators. <sup>1),2)</sup>
2.1 Simple validation
username
<validateAs: 'string'> "should be a string"
<validateAs: 'notBlank'> "notBlank ~ should not be an empty string or whitespace"
^ username
2.2 Collection validation (note that ALL collection elements must conform to the declared validation pragmas)
emails
<validateAs: '#string'>
<validateAs: '#email'> "the '#' signifies that emails shoule be a collection"
"the 'email' signifies that each element of the collection"
"should be a string containing a valid email"
^ emails
- Validate the object once filled. If the validations find a problem,
PragmaValidationError
will be raised.
| r |
r := RegistrationRequest new username: 'john'; emails: {'john@smalltalk.com'. 'jsmith@acme.com'}; validate.
- Note that annotating a mutator or an accessor with a protocol different than "accessing" will not work.
2)The accessors are called in the process of validation, thus one must add additional code to them with caution.
📑 Supported validations
Validation | Usage Example | Description |
---|---|---|
notNil | <validateAs: 'notNil'> | Accessor value is not nil |
assertTrue | <validateAs: 'assertTrue'> | Accessor value |
size:MIN,MAX | <validateAs: 'size:1,3'> | Accessor value has a size between the attributes MIN and MAX; can be applied to any collection |
min:VAL | <validateAs: 'min:100'> | Accessor value has a value no smaller than VAL |
max:VAL | <validateAs: 'max:1000'> | Accessor value has a value no larger than VAL |
email | <validateAs: 'email'> | Accessor value is a valid email address |
notEmpty | <validateAs: 'notEmpty'> | Accessor value is not null or empty; can be applied to any collection |
notBlank | <validateAs: 'notBlank'> | Accessor value is not null, empty string or string containing solely whitespace |
positive | <validateAs: 'positive'> | Accessor value is strictly positive number |
positiveOrZero | <validateAs: 'positiveOrZero'> | Accessor value is strictly positive number, or 0 |
negative | <validateAs: 'negative'> | Accessor value is strictly negative number |
negativeOrZero | <validateAs: 'negativeOrZero'> | Accessor value is strictly negative number, or 0 |
datetimeString | <validateAs: 'datetimeString'> | Accessor value is a string containing date and time |
past | <validateAs: 'past'> | Accessor value is a string containing date and time which is in the past |
future | <validateAs: 'future'> | Accessor value is a string containing date and time which is in the future |
🎁 Installation
Metacello new
baseline: 'PragmaValidators';
repository: 'github://radekbusa/Pragma-Validators';
load.
🔌 Integration example
Let's say that we want to use the pragma validators for validating JSON request bodies in our RESTful API.
- In a controller or a Teapot filter, write:
| body parsedBody |
body := aRequest entity string.
parsedBody := NeoJSONReader fromString: body as: RegistrationRequest.
parsedBody validate. "will validate each incoming request body"
🧩 Compatibility
Tested in Pharo 7, 8 and 9.
👨💻 Author
Radek Busa is the author and maintainer of this project.
- Tech blog: www.medium.com/@radekbusa
- Hire me for your next Smalltalk project: www.radekbusa.eu
"I love building enterprise-grade software products in no time and Pharo greatly contributes to that with its amazing debugger, test-driven environment and other great stuff, such as refactoring tools. My vision is to build libraries for ultra-productive enterprise microservice development with minimalistic and easy-to-grasp APIs for Smalltalk in 2020s."
If you endorse my vision and/or this project helped you, please don't hesitate to donate. Your donations will be welcome!