Dynamic Web Development with Seaside

26.5Adding Validation

Descriptions can have predicates associated with them to validate the input data. Magritte calls such validation conditions associated with a description. A condition is simply a block that returns true or false. A simple one is the single field condition which is passed the pending value directly and can be attached directly to your descriptions. It is as simple as the following block which checks the length of the value once the blanks are removed.

aDescription addCondition: [ :value | value withBlanksTrimmed size > 3 ] 

There are advantages to having your rules outside your domain objects, especially if you’re taking advantage of Magritte as an Adaptive Object Model where users can build their own rules. It also allows the mementos to easily test data for validity outside the domain object and gives you a nice place to hook into the validation system in the components. Still you have to pay attention since it may weaken your domain model.

Multiple Field Validation. When we did the Mini-reservation example in previous chapters we wanted the starting date to be later than today. With Magritte we can express this point as follows:

descriptionStartDate
^ MADateDescription new
accessor: #startDate;
label: 'Start Date';
addCondition: [ :value | value > Date today ];
beRequired;
yourself
descriptionEndDate
^ MADateDescription new
accessor: #endDate;
label: 'End Date';
addCondition: [ :value | value > Date today ];
beRequired;
yourself

Now to add a validation criterion that depends on several field values, you have to do a bit more than that because you cannot from one description access the other. Suppose that we want to enforce that the endDate should be after the startDate. We cannot add that rule to the endDate description because we cannot reference the startDate value. We need to add the rule in a place where we can ensure all single field data exists but before it’s written to the object from the mementos.

We need to add a rule to the objects container description like this

descriptionContainer 
^ super descriptionContainer
addCondition: [ :object |
(object readUsing: self descriptionEndDate) >
(object readUsing: self descriptionStartDate)]
labelled: 'End date must be after start date';
yourself

This simply intercepts the container after it is built, and adds a multi field validation by accessing the potential value of those fields. You get the memento for the object, and all the field values are in its cache, keyed by their descriptions. You simply read the values and validate them before they have a chance to be written to the real business object. Multi field validations are a bit more complicated than single field validations but this pattern works well.

Copyright © 19 March 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.