Home | Projects | Contact Me

My First Steps With Transfer : Day 3

Well, this is the third and final installment of my blog posts dealing with my crash-course in Transfer ORM. On the first day I roughed out my transfer.xml file that detailed my database structure and wrote the rudimentary functions that compose the gateway object WhosOnCFC uses to communicate with the database. On the second day I fleshed out some new functions that mimic the array functions in WhosOnCFC. Day three links the ActiveUsers table with a One-to-Many relationship to the PageHistory table which stores each page viewed by a session.

Here is the new transfer.xml file showing the relationships in our tables:

<InvalidTagDefinitions>

<package name="whosoncfc">

<InvalidTag name="user" table="ActiveUsers">
<id name="ClientID" type="string" />
<property name="UserID" type="string" />
<property name="Roles" type="string" nullable="true" />
<property name="Created" type="date" />
<property name="LastUpdated" type="date" />
<property name="Referer" type="string" nullable="true" />
<property name="IP" type="string" />
<property name="HostName" type="string" />
<property name="HideClient" type="boolean" />
<property name="Coords" type="string" nullable="true" />
<property name="Country" type="string" nullable="true" />
<property name="City" type="string" nullable="true" />
<property name="EntryPage" type="string" />
<property name="CurrentPage" type="string" />
<property name="HitCount" type="numeric" />
<property name="UserAgent" type="string" nullable="true" />
<onetomany name="pageHistory" lazy="true">
<link to="whosoncfc.pageHits" column="ClientID" />
<collection type="array" />
</onetomany>
</object>

<InvalidTag name="pageHits" table="PageHistory">
<id name="ClientID" type="string" />
<property name="Page" type="string" />
<property name="LoadTime" type="date" />
</object>

</package>

</objectDefinitions>

If you are playing along at home you will notice we added in a new object, whosoncfc.pageHits which we will use to store our history. It is a very simple table comprised of a ClientID, the page being viewed, and the time the page was loaded. Whosoncfc.user is linked to this table with Many-to-One relationship. I added the lazy="true" parameter so the data is only loaded when it is needed. I have read through so many documents and blogs lately, I seemed to remember this might be the behavior I wanted. I am sure someone will be happy to correct me if I am wrong.

I am not going to post up the whole code for the gateway object again, but I will show some of the things I found pretty interesting. The utilitity function that purges our expired information has been updated with a cascaded delete function that keeps both of our tables nice and clean. A line of code replaced two queries I would have had to written by hand:

<cffunction name="purgeUsers" returntype="boolean" access="public" hint="I get rid of expired data">
<cfargument name="trackTime" type="numeric" required="true" hint="How many hours to track usrs" />
<cfargument name="botTrackTime" type="numeric" required="true" hint="How many hours to track bots" />

<cfset var transfer=variables.transfer.getTransfer() />
<cfset var uQuery = "" />
<cfset var user = "" />

<cfset uQuery=transfer.list("whosoncfc.user") />

<cfloop query="uquery">
<cfif uQuery.HideClient is false>
<cfif dateDiff("n",uQuery.LastUpdated,Now()) gte (60*arguments.trackTime)>
<cfset user=transfer.get('whosoncfc.user',uQuery.ClientID) />
<cfset transfer.cascadeDelete(user) />
</cfif>
<cfelse>
<cfif dateDiff("n",uQuery.LastUpdated,Now()) gte (60*arguments.botTrackTime)>
<cfset user=transfer.get('whosoncfc.user',uQuery.ClientID) />
<cfset transfer.cascadeDelete(user) />
</cfif>
</cfif>
</cfloop>

<cfreturn true />
</cffunction>

Another little interesting bit is where the history is actually added to the database. Generally I would have just done a straight insert into the database and worried about querying it out later on. In Transfer we get the parent object, which in this case is going to be whosoncfc.user. Then we create an object for whosoncfc.pageHit, populate it with data, and set the parent object to our user object then call the create() member to actually insert it. It looks like this:

<cffunction name="addHistory" returntype="boolean" access="public" hint="I add a page to the history">
<cfargument name="userData" type="struct" required="true" />

<cfset var thisHit = "" />
<cfset var thisUser = "" />
<cfscript>

thisUser=variables.transfer.getTransfer().get('whosoncfc.user',arguments.userData.ClientID);
thisHit=variables.transfer.getTransfer().new('whosoncfc.pageHits');

thisHit.setPage(arguments.userData.CurrentPage);
thisHit.setLoadTime(Now());

thisHit.setParentUser(thisUser);

variables.transfer.getTransfer().create(thisHit);

return true;
</cfscript>
</cffunction>

These were the major changes from day two so I did not see any point in including the entire component here. I would like to think that in the first three days of playing with Transfer I did manage to get a decent grip of handling database interactions. I have not even looked into Transfer decorators, observers, TQL or many of the other advanced features available. I did learn one important lesson though, Transfer makes dealing with databases painless. Because of the learning curve it did take me a couple extra days to get everything written but next time I imagine it will go by much quicker.

If you have been hiding under a rock and do not know what Transfer is I encourage you to look it up and learn more about it. If, like me, you are hard-headed and have avoided picking it up for one reason or another it would be a good chance to take a look at it. My excuse was I was too busy, I had too much on my plate, I didn't have time to learn how to use it, etc. Mark Mandel has done an excellent job on Transfer and I would have probably saved myself a lot of time had I picked it up sooner. I believe Mark just released the new RC for Transfer 1.1 so now would be a great opportunity to pick it up.

Related Blog Entries

Comments
Layout: Shane Zehnder ::: BlogCFC was created by Raymond Camden. ::: This blog is running version 5.9.