Neptune 1.0 Beta 3 Documentation: Custom Logic

Neptune Information

Download from RIA Forge

Custom Logic

The "Getting Started" section covers how to create a CRUD application, but most applications will have more than simple data management to them. So, it must be easy to add custom logic.

Of course, any custom logic should be covered by automated tests. It is easy to do, so go read about testing in Neptune now. Seriously, you really need to do that first. It won't take long.

You read about testing? Good. Then we can proceed.

Our client wants to make sure that any contact that has a name of "Smithe" gets changed to "Smith".

Let's look at the virtual "Contacts" component. This is not the actual code, but the most commonly used methods and what code they would have if we wrote them manually:

<cfcomponent extends="com.sebtools.Records" output="no">

<cffunction name="getContact" access="public" returntype="query" output="no">
	<cfargument name="ContactID" type="numeric" required="true">
	
	<cfreturn getRecord(ArgumentCollection=Arguments)>
</cffunction>

<cffunction name="getContacts" access="public" returntype="query" output="no">
	
	<cfreturn getRecords(ArgumentCollection=Arguments)>
</cffunction>

<cffunction name="removeContacts" access="public" returntype="void" output="no">
	
	<cfset removeRecord(ArgumentCollection=Arguments)>
	
</cffunction>

<cffunction name="saveContact" access="public" returntype="string" output="no">
	
	<cfreturn saveRecord(ArgumentCollection=Arguments)>
</cffunction>

<cffunction name="validateContact" access="public" returntype="struct" output="no">
	
	<cfreturn Arguments>
</cffunction>

</cfcomponent>

We certainly don't need to write all of that code out every time, but it can be helpful to know what it would look like. Now, back to our mission. Let's add an "adjustContactName" method:

<cffunction name="adjustContactName" access="private" returntype="string" output="no">
	<cfargument name="ContactName" type="string" required="true">
	
	<cfset Arguments.ContactName = Replace(Arguments.ContactName,"Smithe","Smith")>
	
	<cfreturn Arguments.ContactName>
</cffunction>

Once we have that method in place, we can create a custom "validateContact" method (which is called by saveRecord just before it saves the data) to use it:

<cffunction name="validateContact" access="public" returntype="struct" output="no">
	
	<cfif StructKeyExists(Arguments,"ContactName")>
		<cfset Arguments.ContactName = adjustContactName(Arguments.ContactName)>
	</cfif>
	
	<cfreturn Arguments>
</cffunction>

Here would be our new Contacts.cfc:

<cfcomponent extends="com.sebtools.Records" output="no">

<cffunction name="adjustContactName" access="private" returntype="string" output="no">
	<cfargument name="ContactName" type="string" required="true">
	
	<cfset Arguments.ContactName = Replace(Arguments.ContactName,"Smithe","Smith")>
	
	<cfreturn Arguments.ContactName>
</cffunction>

<cffunction name="validateContact" access="public" returntype="struct" output="no">
	
	<cfif StructKeyExists(Arguments,"ContactName")>
		<cfset Arguments.ContactName = adjustContactName(Arguments.ContactName)>
	</cfif>
	
	<cfreturn Arguments>
</cffunction>

</cfcomponent>

Now we can run our test to verify that this meets our business rule. If we find a use-case that this code doesn't meet, we can just write another test and then modify our code to make it pass.

The point here isn't the specific implementation of this business rule, but rather how to add custom logic into a Records component used by Neptune.

The same basic approach should work for any custom logic that we want to add.

Next: Email Notices