So now you know why I needed a database abstraction system. You also know that I chose the Illudium PU-36 Code Generator because of it's templating system. Having the templating system gave me full control to generate exactly the kind of CFCs that I wanted. I'll go over some of the ways that I modified the stock templates in another post in this series.
The biggest issue I had with Illudium was that it very quickly became tedious to have to go into the Flex interface, re-enter all the information in the form and re-generate the CFCs every time I made a tweak to the templates. And let's be honest. It's going to be an iterative process to get the templates right.
So, I decided to see if I could call the CFCs that back the GUI outside of it. Then, I would be able to run a script and quickly re-generate the CFCs whenever I wanted to. If I remember right, I found what CFC and method were being called by watching the new monitoring tools in CF8. Then I started digging into the code that the Illudium remote facade calls. I mocked up the code that should work to get back a package of generated code for one table. But, it didn't work right away. I had to change a little bit of the code in one method of codeService.cfc to get it working. Oddly, the file pathing seems to change when something is being called by remoting vs. CreateObject().
Below is the updated code for that method. I've also attached a zip that has a patch file if you'd like to just patch the cfc in Eclipse.
<cffunction name="processCFMTemplate" access="private" output="false" returntype="string">
<cfargument name="template" type="string" required="true" />
<cfargument name="xmlTable" required="true" type="xml" />
<cfset var content = "" />
<cfset var root = arguments.xmlTable.root />
<cfset var tempFileName = "#createUUID()#.cfm" />
<cfset var tempDirPath = getDirectoryFromPath(getCurrentTemplatePath()) & "temp" />
<cfif not directoryExists(tempDirPath)>
<cfdirectory action="create" directory="#tempDirPath#">
</cfif>
<!--- write the cfm to a hard file so it can be dynamically evaluated --->
<cffile action="write" file="#tempDirPath#/#tempFileName#" output="#arguments.template#" />
<cfsavecontent variable="content">
<cfinclude template="temp/#tempFileName#" />
</cfsavecontent>
<cfset content = replaceList(content,"<%,%>,%","<,>,##") />
<cffile action="delete" file="#tempDirPath#/#tempFileName#" />
<cfreturn content />
</cffunction>
Also, here is what the code for calling Illudium outside of the GUI looks like.
<!--- Path to Illudium xsl folder --->
<cfset xslBasePath = "/cfcgenerator/xsl/" />
<!--- Start of path to generated CFCs --->
<cfset ObjectStore = "com.generated.test" />
<cfset DataSource = "YOURDSNAME" />
<cfset Table = "ATABLENAME" />
<!--- Load Illudium PU-36 Code Generator Service --->
<cfset gs = createObject("component","cfcgenerator.com.cf.model.generatorService").init(xslBasePath) />
<cfset gs.setAdminPassword("YOURCFADMINPASSWORD") />
<cfscript>
/* Illudium wants a path that doesn't include the trailing '/' */
rootPath = mid(ExpandPath('/'),1,len(ExpandPath('/'))-1);
/* Illudium Args */
args = {
dsn = DataSource,
componentPath = ObjectStore & '.' & DataSource & '.' & Table,
table = Table,
projectPath = 'dealerpeak_base',
stripLineBreaks = 'yes',
rootPath = rootPath
};
basecode = gs.getGeneratedCFCs(argumentCollection=args);
</cfscript>
<!--- Separate folder for each Datasource --->
<cfset DataSourceDir = rootPath & '/' & replace(ObjectStore,'.','/','all') & '/' & DataSource />
<!--- Make sure datasource directory is there --->
<cfif NOT directoryExists(DataSourceDir)>
<cfdirectory action="create" directory="#DataSourceDir#">
</cfif>
<!--- Create CFC files --->
<cfloop from="1" to="#arrayLen(basecode)#" index="i">
<cffile action="write" file="#basecode[i].getFilePath()#" output="#basecode[i].getContent()#" />
</cfloop>
So, have fun playing with the Illudium PU-36 Code Generator! I'll be back soon to discuss bundling this up into a CFC generator object.