<cffunction name="validateTestee" access="public" returntype="any"
output="false"
hint="Validates a testee.">
<cfargument name="testee" type="testee" required="true" />
<cfargument name="eH" type="myApp.model.sys.error.errorHandler"
required="false" />
<cfif NOT StructKeyExists(arguments, "eH")>
<cfset arguments.eH = CreateObject("component",
"myApp.model.sys.error.errorHandler").init() />
</cfif>
<cfif NOT ListFindNoCase("active|archived",
arguments.testee.getStatuscode(), "|")>
<cfset arguments.eh.setError("statuscode",
"testee.statuscode.invalid") />
</cfif>
<cfif Len(arguments.testee.getFirstName()) LT 2>
<cfset arguments.eh.setError("firstName",
"testee.firstName.invalid") />
</cfif>
<cfif Len(arguments.testee.getFirstName()) GT 50>
<cfset arguments.eh.setError("firstName",
"testee.firstName.tooLong") />
</cfif>
<cfif Len(arguments.testee.getLastName()) LT 2>
<cfset arguments.eh.setError("lastName",
"testee.lastName.invalid") />
</cfif>
<cfif Len(arguments.testee.getLastName()) GT 50>
<cfset arguments.eh.setError("lastName",
"testee.lastName.tooLong") />
</cfif>
<cfif Len(arguments.testee.getSuffix())
AND NOT ListFindNoCase("Jr|Sr|II|III|IV",
arguments.testee.getSuffix(), "|")>
<cfset arguments.eh.setError("suffix",
"testee.suffix.invalid") />
</cfif>
<cfif
REFindNoCase("^(0[13578]|1[02])/(0[1-9]|[12][0-9]|3[01])|(0[469]|11)/(0[1-9]|[12][0-9]|30)|(02)/(0[1-9]|[12][0-9])$",
arguments.testee.getBirthDate()) EQ 0>
<cfset arguments.eh.setError("birthDate",
"testee.birthDate.invalid") />
</cfif>
<cfif Len(arguments.testee.getEmployeeNumber()) GT 20>
<cfset arguments.eh.setError("employeeNumber",
"testee.employeeNumber.tooLong") />
</cfif>
<cfreturn eH />
</cffunction>
Basically, the error handler (message handler is more aptly named) has
structs for error message keys to be set and offers a nice API
(hasErrors(), hasInformations(), setError(), getError()). The keys
(i.e. "testt.employeeNumber.tooLong") are used to look up the messages
as defined by our content editors. The messages are housed in a
home-grown XML file and loader. We use custom tags to look things up.
You'll see similar ideas for the validation framework package we're
going to introduce in Mach-II 1.9.
> Are you using ORM?
>
No, we're using mostly generated hand tweaked DAOs/Gateways to work with
our database.
> Also, do you think you could expound a little more (or maybe point me
> toward a wiki page) on how you're handling I18N? It's kind of off-
> topic for this thread, but it's an area of professional curiosity for
> me.
>
Yeah, an area I'm struggle with at the moment -- it's kludge of
different things from a home grown message key translation system to
using things like resource bundles (Java). That's from the page view
perspective. Organizing a site with i18n is different beast. Questions
like reusing events and setting the language or having separate events
for each language. Depends on the application -- for pure translations
of "brochure" stuff that is not managed in a CMS we opted for a new
event-handler for each language (we name events then using that language
or setup Mach-II URL routes). For app like pages such as basic forms
where we can get away with simple translations of labels, we used a
single event and set a language for it.
i18n is something we're discussing for 1.9 as that ties into the
validation stuff (we want validation to by i18n ready).
> Also again, is there an M2SFP or some wiki page for validation that we
> could read and comment on?
>
An area where the wiki needs some help to be honest. It's more of an
how can I do validation in OO CFML applications than specific Mach-II
issue and which is why it hasn't gotten the attention it needs by the
team. Care to start developing one?
Best,
.Peter
So how will this work with ORM? I'm using the same flow as yours but I
don't think it will work with ORM on the "Add New" forms. Since the
event-bean calls setter on primary key as well, which is of type
"generator", entitySave() will always perform update instead of
insert.
Can we, somehow, specify the event-bean to not call setter on primary
key if it is blank?
Sumit Verma said the following on 11/22/2009 02:07 PM:
> Yes, overriding the setter in the bean is an option. I was trying toWell, over time your beans will be more than table definitions -- or
> not add any method in the bean itself and keep only table definition,
> but I think the setter for ID is needed. It will allow me to remove
> the check from the constructor in base entity.
you'll have a pretty anemic domain model. I wouldn't worry about having
to define an occasional setter/getter/other method. No bean is going to
always be the same so an exception to the normal rules is fine. If your
PK is always going to be ID, then you define the setId() method in your
base class.
>Well, nulls in Java and nulls in Adobe CF are the same thing unless they
> From what I have tested so far, I don't think we can reset the ID in
> save method because it looks like cf/hibernate expects PK (identity)
> to be null but there no way to set it to null!! I'm not sure if
> setting it to a java null will work.
are doing something weird with the ORM implementation. I didn't test
this, but I would think you should be able to do:
<cfset variables.id = JavaCast("null", "") />
HTH,
.Peter
Well, no null in Adobe CF :o) From javacast documentation:Note: Do not assign the results of JavaCast("null","") to a ColdFusion variable. Unexpected results will occur.
Thanks a lot you guys for being so responsive. Makes the learning curve much shorter and experience much better!
--