>> GreenByte.info By Nick Tong (quiksilv) | Supported by: TalkWebSolutions.co.uk

Setting up and using Transfer within fusebox via the Transfer lexicons

Setting up Transfer within fusebox via the Transfer lexicons

After my previous post where I cover Setting up Coldspring within fusebox via the CS lexicons I've now just got Transfer working with the Transfer lexicons.

To get Transfer setup you need to initilise the Transfer factory, you do this using the initialize verb. The best place to do this is in the appinit section of fusebox.xml.cfm as this is called when you start your app (it's like the onApplicationStart function in application.cfm). Within this function I call a fuseaction in my model circuit:

<appinit>
<fuseaction action="m.transferSetup" /> </appinit>
Then inside my model circuit I have this fuseaction
...
<circuit access="public" xmlns:tr="transfer/">
<fuseaction name="transferSetup">
<tr:init
            datasource="/config/datasource.xml.cfm"
            configuration="/config/transfer.xml.cfm"
            definitions="/model/transferData" />

</fuseaction>

So what's heppening here:

<circuit access="public" xmlns:tr="transfer/"> - we're declaring the namespace for the transfer lexicons
tr:init - this calls the initialize verb from the transfer lexicon folder to get Transfer setup.
datasource="/config/datasource.xml.cfm" - this is telling Transfer where to find the datasource config file.
configuration="/config/transfer.xml.cfm" - this is telling Transfer where to find the Transfer config file.
definitions="/model/transferData" - this tells transfer where to put it's generated code

One you run this code Transfer is up and running. Thats it, nothing else left to do. You now have access to all of Transfers features.

Next you'll want to configure Transfer to tell it how all the tables are setup and related (we'll take a simple example here):

<?xml version="1.0" encoding="UTF-8"?>
<transfer xsi:noNamespaceSchemaLocation="/transfer/resources/xsd/transfer.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<objectDefinitions>
      <package name="user">
         <object name="user" table="tblUser">
            <!-- generate tells the DB if we need to create a unique key for inserts -->
            <id       name="userID"          type="numeric" generate="false" />
            <property    name="contactName"       type="string" />
            <property    name="userPassword"      type="string" />
            <property    name="email"          type="string" column="emailAddress" />
            <property    name="userTypeID"       type="string" />
            <property    name="lastLogin"       type="date" />
            <property    name="live"             type="boolean" />
             <onetomany name="address">
                <link column="userID" to="address.address" />
             </manytoone>
         </object>
      </package>
      <package name="address">
         <object name="address" table="tblAddress">
            <id name="addressID"          type="numeric" />
            <property name="address1"       type="string"    column="address1" />
            <property name="address2"       type="string"    column="address2" />
            <property name="address3"       type="string"    column="address3" />
            <property name="town"          type="string"    column="town" />
            <property name="country"       type="string"    column="country" />
            <property name="postCode"       type="string"    column="postCode" />
            <property name="addressTypeID"    type="numeric"    column="addressTypeID" />
            <property name="refID"          type="numeric"    column="refID" />
            <property name="live"          type="boolean"    column="live" />
            <property name="county"       type="string"    column="county" />
            <manytoone name="addressType">
                <link column="addressTypeID" to="address.addressType" />
             </manytoone>
         </object>

         <object name="addressType" table="tblAddressType">
            <id name="addressTypeID"       type="numeric" />
            <property name="addressType"    type="string" column="addressType" />   
         </object>
      </package>
</objectDefinitions>
</transfer>

So what's the deal here:


<objectDefinitions> - this just declares that you're starting you object definitions
<package name="user"> - this is a neat way to group your objects together (you don't require this)
<object name="user" table="tblUser"> - this setup your object and gives it its name and tells it what table it refers to
<id ...- this is your primary key on the table
<property ... - we use property to list the table columns you want to return. Note you can use any name as long as you tell the property what column to use i.e. <property name="email" type="string" column="emailAddress" />
<onetomany name="address"> - this is telling Transfer that I want to join my user table to my address table, where the I have One user and Many Address
<link column="userID" to="address.address" /> - this is what I join the tables on. I'm telling transfer to look at the address object in the address package and join on userID.

Okay so you now have you Transfer factory created and you have Transfer set up, next you'll want to get data from Transfer. Lets start with looking at what you can do with the fusebox lexicons:

init - we've covered this already above
parameter - this allows you to pass in variables to the read verb
read - this allows you to get a single record
list - this allows you to get a list of records
save - Save records
delete - delete records
populate - Populates a Transfer object with query data

Okay so now we know what lexicons we can use fusebox lets look at a fuseaction (in our model) using the read verb:

<fuseaction name="checkLogin">
<tr:read object="user.user" bean="checkLogin">
<tr:parameter name="email"          value="#attributes.email#" />
<tr:parameter name="userPassword"    value="#attributes.password#" />
<tr:parameter name="live" value="1" />
</tr:read>
</fuseaction>
In this fuseaction we are asking Transfer to get the user object from the user package setup in the Transfer configuration file. We pass in a email address and password form a form this read. We then reference the result using the bean name, in this case 'checkLogin'.
So let say we call the checkLogin fuseaction from our controller:

<fuseaction name="checkLogin">
      <do action="m.checkLogin" />
      <if condition="(checkLogin.getUserID())">
         <true>
            <do action="vendor-m.setSession" />
            <relocate url="#request.myself##xfa.myAccount#" />
         </true>
         <false>
            <relocate url="#request.myself##xfa.login#&amp;loginError=1" />
         </false>
      </if>
</fuseaction>

Here we have called our checkLogin fuseaction from our model circuit, we then look at the returned bean 'checkLogin'. If it can find a userID then Transfer has found a record. We're happy with this so we setup the session variables and relocate to the user to the account area.
If the userID can't be found then there has been an error with the login so we redirect the user back to the login page.

Wait a second, where did getUserID() come from?
Well as Transfer knows that my table has a userID field, it cleverly goes of and creates getters and setters for that field (as well as any other table field you setup in the config file). We then simple call these getters and setters prefixing the tableField with get or set. How cool is that. Now we've got that clear did you notice we've not written one line of SQL?

Transfer a a very powerful tool and I hope to cover more of what it can do when i delve in deeper. Mark Mandel has done a great job. You can listen to Mark talk about Transfer over on cfFramworks.com

I can't recommend downloading and playing with it enough!


 
Comments
Mark Mandel's Gravatar Thanks for that!

I've added this article to the 'getting started' documentation section under 'framework tutorials' that will be released with the next version.

Thanks!
# Posted By Mark Mandel | 27/03/07 23:59 | Report abusive comment
dickbob's Gravatar Good leg up, thanks.

Minor typo - xmlns:tf="transfer/" should be xmlns:tr="transfer/"
# Posted By dickbob | 28/03/07 12:59 | Report abusive comment
nick tong's Gravatar @Mark - My name in documentation... thanks very much :)

@dickbob AKA Eagle eyes ;) - many thanks, I've updated it.
# Posted By nick tong | 28/03/07 15:34 | Report abusive comment
dickbob's Gravatar Nick@ - No worries. I'm glad you posted this. I didn't know that there was a Transfer lexicon in the Fusebox Subversion repository. So the typo got teased out when I tried to implement it.

One thing I'm not sure about and I don't know if you have an opinion on it is, how do I handle an app with two DSN's? I realise that I can have more than one datasource/configuration file and definitions location but what about the TransferFactory created by the init verb? I assume that I should have a Factory per DSN/database? Should the lexicons be extended to support an optional Factory name? Should I really be directing these issues to the author (Sean) of the lexicons or having a go at posting an update myself?

Or am I just plain wrong! :-)
# Posted By dickbob | 29/03/07 07:46 | Report abusive comment
nick tong's Gravatar @dickbob - i think you have a valid point and one that should indeed be brought up for viewing by Sean.
# Posted By nick tong | 30/03/07 17:32 | Report abusive comment
Mark Mandel's Gravatar I finally blogged this post.

About time ;o)

Mark
# Posted By Mark Mandel | 09/04/07 09:15 | Report abusive comment
Richard Tugwell's Gravatar This is such a great "little" post. I appreciate that it's Mark and Sean who have done a ton of work, but sometimes it's a little "for-example" like this that I need to get me kick started
# Posted By Richard Tugwell | 19/04/07 07:46 | Report abusive comment
nick tong's Gravatar Hi Richard, thanks for you kind comment, it's great to get feedback.
# Posted By nick tong | 19/04/07 10:12 | Report abusive comment
Wally Kolcz's Gravatar I am little behind and a lot confused. I see the setup

<circuit access="public" xmlns:tr="transfer/">
<fuseaction name="transferSetup">
<tr:init
datasource="/config/datasource.xml.cfm"
configuration="/config/transfer.xml.cfm"
definitions="/model/transferData" />
</fuseaction>

but I don't see where you get the various files.

/config/datasource.xml.cfm"
/config/transfer.xml.cfm"
/model/transferData

Thanks.
# Posted By Wally Kolcz | 07/07/07 23:13 | Report abusive comment
Erik-Jan Jaquet's Gravatar Great tutorial! Any suggestions on how to use both Coldspring and Transfer together in Fusebox?
# Posted By Erik-Jan Jaquet | 11/07/07 19:02 | Report abusive comment
James Buckingham's Gravatar Hi Nick,

I've just started messing around with Fusebox and my starting point on the road to understanding Transfer has been through your great tutorials.

I'm really starting to see the potential of this, the first example I setup removed 3 cfcs full of SQL straight away, but there is something about having the start of my SQL management inside the Fusebox that doesn't sit comfortably with me.

Maybe it's my lack of understanding but if I was looking to use Transfer for my DB management layer then I would expect to see it happening within CF files within my model/controller rather than right inside the circuits themselves.

I guess what I'm trying to say is what would be the advantage of this way over a more "traditional" approach?
# Posted By James Buckingham | 12/03/08 21:52 | Report abusive comment
BlogCFC was created by Raymond Camden. This blog is running version 5.5.1.