Photo from Chile

Easy Access to Primary Keys in Transfer Objects

I just added a couple of new methods to my AbstractTransferDecorator to make some of my ColdFusion development tasks easier. I found that when trying to write abstract code I needed to know the name of the primary key column of my object, and also sometimes needed to know the value of that column for the current object. So I wrote two new methods to address those needs:

  • __getPKColumn() - Returns the name of the id column for the current object.
  • __getPKValue() - Returns the value of that column for the current object.

I chose to prefix the method names with a double underscore so I wouldn't end up overwriting the getters if any of my objects ever have those names as properties. Although I'm fairly certain that would never happen it seems like a good idea nonetheless. Here's the code:


Transfer's getMemento() has Changed

Although I have been fairly vocal about the fact that the getMemento() method available from Transfer (an ORM for ColdFusion) is undocumented and subject to change, and have even written my own implementation of it in my AbstractTransferDecorator, I discovered today that I am still calling it one place in my ColdFusion application code (which I wrote a long time ago). And that one line of code is now throwing an error. I understand from some comments on Jason Dean's blog that the internal implementation of mementos did change recently, in Transfer 1.1 according to Mark Mandel, which explains my problem.

I just thought it would be worth sharing this with the community, as I have a feeling that I'm not the only one to use getMemento() on occasion. So be warned: if any of your code uses getMemento() test it with the latest BER of Transfer as you may need to make changes to your code before deploying Transfer 1.1.

How I Use Transfer - Part X - My Abstract Transfer Decorator Object - Validations

In the previous post in this series about Transfer (an ORM for ColdFusion) I discussed the populate() method of my AbstractTransferDecorator. Having discussed some of the simple methods of this object in the post prior to that, what remains is a discussion of how I'm currently using this object to do validations.

There are three methods in this object that are used to support validations in my apps:

  • getValidations() - This returns an array of business rules that apply to the Business Object.
  • addValidation() - This is a helper method to make defining validations simpler.
  • validate() - This contains generic validation routines that are shared by all Business Objects.

Let's start with getValidations(), which returns an array of business rules. This array does not include any information about implementing those rules, it simply describes the rule, and any requirements for the rule. For example, one rule might be Required, which simply means that the user must enter a value for the property. Another rule might be Range, in which case the array item would also include the upper and lower limits of the range. One of the nice things about this approach is that this array can be used to generate both client side and server side validations. So I only have to describe the validations for a given object once in my app, and then I have additional pieces of code which take these rules and automatically generate the JavaScript required for client validations, and the CF code required for server side validations. We'll see an example of the latter when we discuss the validate() method later in this post.


How I Use Transfer - Part IX - My Abstract Transfer Decorator Object - The Populate Method

In the previous post in this series about Transfer (an ORM for ColdFusion) I introduced my AbstractTransferDecorator and discussed some of its simpler methods. In this post I want to go through the populate() method in detail. I have posted bits and pieces of this method in the past, but I don't think I've ever documented the whole thing, as it stands today. I'll break it into pieces to make it a bit more manageable.

view plain print about
1<cffunction name="populate" access="public" output="false" returntype="void" hint="Populates the object with values from the argumemnts">
2    <cfargument name="args" type="any" required="yes" />
3    <cfargument name="FieldList" type="any" required="no" default="" />
5    <cfset var theFieldList = "" />
6    <cfset var TransferMetadata = getTransfer().getTransferMetaData(getClassName()) />
7    <cfset var Properties = TransferMetadata.getPropertyIterator() />
8    <cfset var theProperty = 0 />
9    <cfset var varName = 0 />
10    <cfset var varType = 0 />
11    <cfset var varValue = 0 />
12    <cfset var CompType = 0 />
13    <cfset var hasIterator = false />
14    <cfset var theIterator = 0 />
15    <cfset var theComposition = 0 />
16    <cfset var ChildClass = 0 />
17    <cfset var ChildPKName = 0 />
18    <cfset var theChild = 0 />


How I Use Transfer - Part VIII - My Abstract Transfer Decorator Object - Simple Methods

In the past two posts in this series about Transfer (an ORM for ColdFusion) I discussed how I have implemented my Abstract and Concrete Gateways. As you may recall from Part II, that leaves my AbstractTransferDecorator Object as the final abstract object in my model. There is a lot of code in this object, and I plan to provide a lot of explanation, so I'm going to break this up into a few posts.

My AbstractTransferDecorator acts as a base object for all of my Concrete Decorators, and, because most of my Business Objects are created for me by Transfer, it really acts as an Abstract Business Object. For a basic overview of what a decorator is, and how one is used with Transfer, check out this page from the Transfer docs.

I have blogged about this object a few times before, but the posts in this series will, for now, supercede all of those previous posts, as this object continues to change. In fact, this object has a few methods and techniques the design of which I'm not crazy about right now. There will definitely be changes coming, at some point down the road.


How I Use Transfer - Part VII - A Concrete Gateway Object

In the previous post, I described my Abstract Gateway Object. As I did with the Service Objects, I'm going to take a moment to describe a Concrete Gateway Object as an illustration of how I use the Abstract Gateway. I'll start with a recap of the differences between the Abstract Gateway and Concrete Gateways, followed by a look at the code of a specific Concrete Gateway.

  • The Abstract Gateway Object
  • Is never instantiated as an object.
  • Cannot be used as is.
  • Is only ever used as a base object for Concrete Gateway Objects.
  • There is only one Abstract Gateway Object, called AbstractGateway.cfc.
  • Does not have any Transfer classes associated with it.
  • Concrete Gateway Objects
  • Are instantiated as objects.
  • Methods on them are called by Service Objects.
  • All extend AbstractGateway.cfc.
  • There are many Concrete Gateway Objects, e.g., UserGateway.cfc, ProductGateway.cfc, ReviewGateway.cfc, etc.
  • Have one "main" Transfer class associated with them, but can interact with others via code specific to the Concrete Gateway.

One thing to note here is that my Gateway Objects are all injected into Service Objects via Coldspring, and are only called by Service Objects. So the Service acts as an API to the entire model. If a Business Object needs to call a method on a gateway, it calls it via a Service Object that is injected into the Business Object.


How I Use Transfer - Part VI - My Abstract Gateway Object

In the past few posts in the series I discussed, at length, how I have implemented my service layer, which consists of an Abstract Service Object and Concrete Service Objects. I decided to take it easy this time around and just look at my AbstractGateway Object, as it's pretty simple in comparison.

As with the AbstractService, this object is not meant to be instantiated on its own, but rather acts as a base object which my concrete Gateway Objects extend. There are only three public methods in my AbstractGateway:

  • GetList(), which returns a listing for the default entity
  • GetActiveList(), which returns a listing for the default entity, but only includes Active records
  • ReInitActiveList(), which is used to reinitialize the cached query for the Active List (see below for details)


Previous Entries / More Entries