Skip navigation.

Reactor Tip: Super.validate()

|

Using super.validate to add custom validation to reactor:

If you have been copying the entire validate method from the reactor/project/XXX/validator to your extended object to overload the validate method and add extended custom validation, there is a much cleaner and more elegant way to do this. But first, lets cover some reactor validation basics:

Basic Reactor Validation information

Reactor generates basic validation methods based on database metadata. These validations are held in the base validator objects inside the reactor/project folder.
Reactor provides 2 cfc's that extend the base objects, located in the validator subfolder in your "mapping" directory path(set in your reactor configuration). There is one nonDB specific CFC which is also extended by a DB specific one (with the dbtype appended to the filename). Unless you are doing some database specific stuff on your validations You can use the nonDB specific CFC.

Extending Validation

To add extended validation you will need to write a custom function in one of the extended validator CFC's.

In my example below, we will add validation to check to see if one property of a populated record object is a valid choice based on another property. Here is my validation function

<CFFUNCTION name="validateSkyIsBlue" access="public"  output="false" returntype="reactor.util.ErrorCollection">
<CFARGUMENT name="weatherRecord" hint="I am the Record to validate." required="no" type="reactor.project.MemberManager.Record.weatherRecord" />
<CFARGUMENT name="ErrorCollection" hint="I am the error collection to populate. If not provided a new collection is created." required="no" type="reactor.util.ErrorCollection" default="#createErrorCollection(arguments.weatherRecord._getDictionary())#" />
<!--Blue is only allowed as a selection for Sky for people  whose weathercode = 5-->
<CFIF  arguments.weatherRecord.getsky() is "Blue" and arguments.weatherRecord.getweathercode() neq 5 >
<CFSET arguments.ErrorCollection.addError("weather.sky.noBlueAllowed") /> </CFIF>
<CFRETURN arguments.ErrorCollection />
</CFFUNCTION>

(in my dictionary xml files, i added a definition for weather.sky.noBlueAllowed)

To call this method, we need to overload the validate() method to include this validation as well as the reactor generated validation methods. There are two ways to accomplish this, you can copy the entire contents of the validate method from the base object (which I reluctantly admit I was doing until a few weeks ago), Or you can use the "super" keyword to call the base validate method. You will need to pass in the record and the error collection. Here is my validate method as it exists in the extended object:

<CFFUNCTION name="validate" access="public" hint="I validate an  record" output="false" returntype="reactor.util.ErrorCollection">
<CFARGUMENT name="weatherRecord" hint="I am the Record to validate." required="no" type="reactor.project.WeatherManager.Record.weatherRecord" />
<CFARGUMENT name="ErrorCollection" hint="I am the error collection to populate. If not provided a new collection is created." required="no" type="reactor.util.ErrorCollection" default="#createErrorCollection(arguments.weatherRecord._getDictionary())#" />
<CFSET validateSkyIsBlue(arguments.weatherRecord, arguments.ErrorCollection) />
<CFSET super.validate(arguments.weatherRecord, arguments.ErrorCollection) />
<CFRETURN arguments.ErrorCollection />
</CFFUNCTION>

One error collection is returned containg any or all validation errors.
The benefit of doing this as opposed to copying the validate method from the base object is that now you need to make no change to catch validation for new and modified fields in the database.