onMissingMethod Issue Cleared Up

At LandsofAmerica I've been making extensive use of the onMissingMethod() functionality of CF8 to provide implicit getters and setters. This has worked fantastically well, and I'm never going back to explicitly declaring these unless I have to :). But one problem I've had was with using my implicit getters and setters inside my objects. It just didn't work...

My onMissingMethod() functionality is wrapped up in a base decorator object that all of my base objects extend. It looks like this:

<cfcomponent displayname="Base Decorator" hint="This object provides default methods for all base objects. All base objects should extend BaseDecorator" output="false">

    <cfset variables.instance = StructNew() />

    <cffunction name="init" access="public" returntype="any" output="false">

        <!--- Loop through the arguments and run a setter for each one supplied --->
        <cfloop collection="#Arguments#" item="property">
            <cfif property NEQ "id">
                <cfset set(property, Arguments[property]) />
            </cfif>
        </cfloop>

        <cfreturn this />
    </cffunction>

    <!--- Don't allow the setID method to be called from the outside --->
    <cffunction name="setID" access="private" returntype="void" output="false">
        <cfargument name="ID" type="numeric" required="true" />
        <cfset variables.instance.ID = Trim(Arguments.ID) />
    </cffunction>
    <cffunction name="getID" access="public" returntype="numeric" output="false">
        <cfreturn variables.instance.ID />
    </cffunction>

    <cffunction name="get" access="private" output="false" returnType="any">
        <cfargument name="property" type="string" required="false" default="" />
        <cfargument name="defaultValue" type="any" required="false" default="" />
        <cfset var retVal = "" />
        <cfif Arguments.Property NEQ "">
            <cfif NOT StructKeyExists(variables.instance, Arguments.Property)>
                <cfset set(Arguments.property, Arguments.defaultValue) />
            </cfif>
            <cfset retVal = variables.instance[arguments.property]>
        <cfelse>
            <cfset retVal = variables.instance />
        </cfif>

        <cfif IsSimpleValue(retVal)>
            <cfreturn Trim(retVal) />
        <cfelse>
            <cfreturn retVal />
        </cfif>
    </cffunction>

    <cffunction name="set" access="private" output="false" returnType="void">
       <cfargument name="property" type="string" required="true">
       <cfargument name="value" type="any" required="true">
       <cfset variables.instance[arguments.property] = arguments.value />
    </cffunction>

    <cffunction name="onMissingMethod" output="false">
        <cfargument name="missingMethodName" type="string">
        <cfargument name="missingMethodArguments" type="struct">

        <cfset var property = "">
        <cfset var value = "">

        <cfif findNoCase("get",arguments.missingMethodName) is 1>
            <cfset property = replaceNoCase(arguments.missingMethodName,"get","")>
            <cfif NOT StructIsEmpty(Arguments.missingMethodArguments)>
                <cfset value = arguments.missingMethodArguments[listFirst(structKeyList(arguments.missingMethodArguments))]>

            </cfif>
            <cfreturn get(property, value) />

        <cfelseif findNoCase("set",arguments.missingMethodName) is 1>
            <cfset property = replaceNoCase(arguments.missingMethodName,"set","")>
            <!--- assume only arg is value --->
            <cfset value = arguments.missingMethodArguments[listFirst(structKeyList(arguments.missingMethodArguments))]>
            <cfset set(property,value)>

        </cfif>

    </cffunction>
</cfcomponent>

So within my objects, if I called getSomeValue(), I would get an error that method didn't exist (duh, that's why I have onMissingMethod()). For the life of me I couldn't figure out a way around it, so I just started calling get("SomeValue") while I was inside an object. This was workable, though not necessarily ideal. It means that if I refactor a particular method to make it explicit (by creating a getSomeValue method), then I would need to go through my object and replace all of the get("somevalue") calls with getSomeValue().

Well Ben Nadel just made a post on his blog, Comprehensive ColdFusion Component OnMissingMethod() Testing that solves the problem... When calling an objects internal methods, if you always THIS scope them, then onMissingMethod will fire like it's supposed to.

Thanks Ben, now I have to go through and do all of those find/replaces ;-)

0 responses to “onMissingMethod Issue Cleared Up”

Leave a Reply

Leave this field empty:

Powered by Mango Blog.