ColdFusion Function Injection

In my ColdFusion MVC, I have developer areas that are set up in the same way as the “live” code base. I learned this practice from my day web development job. Basically, I want to not require developers to have to pull in all the live methods to their developer area in order to run their own methods. Mixins are a fairly common practice in object oriented programming that allow you to inject a class into another. You can read more about ColdFusion mixins in particular from Ben Nadel’s post, written back in 2009: Exploring Mixins And ColdFusion Components. I didn’t quite need a full mixin in order to accomplish my task, and I therefore created a method that would simply inject a function (the developer’s function) over another (the live function).

Without function injection, the developer would have had to either manually change all method references to originate from the live components, or pull all of those methods from the live components into their developer area. I also did not want to require them to specifically point to their area in their controller files. If the method exists in their area, use it, if it does not, use the live method. This is another good practice I learned from my job. So, here’s what I came up with. It has not been extensively tested, but seems to do the job. Let me know if you have any issues, suggestions, or comments.

<cffunction name="inject" output="false" access="public" returntype="any" hint="injects a method from giver into receiver object.">
 <cfargument name="receiver" type="any" required="true" hint="the object receiving the method"/>
 <cfargument name="giver" type="any" required="true" hint="the object giving the method"/>
 <cfargument name="functionName" type="string" required="true" hint="the function to be injected"/>
 <cfscript>
  var returnData = structNew();
  structUpdate(arguments.receiver, arguments.functionName, arguments.giver[arguments.functionName]);
 </cfscript>
 <cfreturn arguments.receiver />
</cffunction>

Calling

var isDevAction = find("_", arguments.action) gt 0; //determine if we are in a developer's personal area
if(isDevAction){
 persStart = find("_", arguments.action) + 1;
 persEnd = find(".", arguments.action);
 persCnt = persEnd - persStart;
 internalReqData['personalArea'] = mid(arguments.action, persStart, persCnt); //set the name of the developer's class.
 personalData = createObject("Component", "dev." & internalReqData.personalArea & "." & dataClass); //create an object for the developer's class.
 dataClassObj = inject(dataClassObj, personalData, methodName); //now, inject the function from their developer area over the function from the live class.
}

In my MVC, I have controller actions in the URL, for example: http://www.somesite.com/index.cfm?action=account.register. “account” is the class and “register” is the action. So in the calling code above, I first determine whether we are in a developer’s personal area or a live class. Personal areas are denoted by _ within the controller action in the URL, for example, the live controller action would be “account.register”, and the action for my personal area would be “dev_fischer.register”. My developer model class is simply “fischer.cfc.” So, to get the name of my developer class, I extract the action beginning after “dev_” and ending in the period. I then do a createObject to create the developer class and save a reference to it. I then call my inject method, passing the class I am overwriting a given function for, the class I am overwritten the given function with, and finally, the function name to overwrite.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s