now musing at www.aliaspooryorik.com!

February 20, 2008

Fusebox is self documenting!

Filed under: ColdFusion, Fusebox — aliaspooryorik @ 9:11 am

One of the interesting things about writing your Fusebox app as cfcs is that if you add the hint attribute to each function then you can create documentation for your web site.

If you’re using the traditional XML version of fusebox then look here.

<cfcomponent output="false" hint="I am the Rooms Controller Circuit.">
  <cffunction name="Update" output="false" hint="I update multiple room to a new status.">
    ...
  </cffunction>
  <cffunction name="Overview" output="false" hint="I show an overview of all rooms by status and type.">
    ...
  </cffunction>
  <cffunction name="Add" output="false" hint="I add one or more rooms for the Client.">
    ...
  </cffunction>

  <cffunction name="prefuseaction" output="false">
    <cfargument name="myFusebox" />
    <cfargument name="event" />
    <cfset super.prefuseaction(myFusebox=myFusebox, event=event) />
    ...
  </cffunction>
  <cffunction name="postfuseaction" output="true">
    <cfargument name="myFusebox" />
    <cfargument name="event" />
    <cfset super.postfuseaction(myFusebox=myFusebox, event=event) />
    ...
  </cffunction></cfcomponent>

The screen shot below shows a the auto generated documentation for the Rooms Controller circuit.

Fusebox Self Documentation Screenshot

Here’s the code I used to generate it, just put it in the Application root. I’ve highlighted the variables you may need to change. (If you are using Application.cfc then read this post on Calling non fusebox cfm templates when using Fusebox 5.5’s Application.cfc )

<cfset strControllerCircuitsPath = "controller/" />
<cfset qryCircuits = ControllerCircuits( ControllerCircuitPath=strControllerCircuitsPath ) />
<cfset lstHidefuses = "postfuseaction,prefuseaction" />
<cfoutput>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Document Fusebox Application</title>
<style type="text/css">
body{ font-family:Verdana, Arial, Helvetica, sans-serif;
  font-size:62.5%;
  line-height:1.6em;
  margin: 15px 10 20px 10px;
  padding:0;
  background-color:##FAFAFA;
  color: ##525252;

}
h1{
  font-size:1.4em;
  margin:0 0 16px 0;
  padding:0 0 5px 0;
  border-bottom:1px solid ##e7e7e7;
  color:##5e5e5e;
}
h2{
  font-size:1.2em;
  font-weight:bold;
  padding:12px 0px 2px 3px;
  margin:15px 0 8px 0px;
  border-bottom:1px solid ##e7e7e7;
  color:##5e5e5e;
  clear:both;
}

p, li, dd, dt{font-size:1.1em;}
p{ margin: 0 0 20px 0; }

/* Tables */
table {width:100%;}
caption {text-align:left; font-style:italic}
th {text-align:left; background-color:##CCCCCC}
.property {background-color:##F3F3F3; width:20%;}

ul##nav{
  margin:0px;
  padding:4px 0 4px 0px;
  list-style:none;

}

##nav li{
  display:inline;
  margin:0 2px 0 0;
  padding:0px 10px 0 0px;
  font-size:1.1em;
  float:left;
}

</style>
</head>
<body id="top">
<h1>Fusebox Controller Circuits (cfc)</h1>
<ul id="nav">
<cfloop query="qryCircuits">
  <li><a href="##circuit_#qryCircuits.name#">#qryCircuits.name#</a></li>
</cfloop>
</ul>
<cfloop query="qryCircuits">
  <h2 id="circuit_#qryCircuits.name#">#qryCircuits.name#</h2>
  <cfset sCircuitName = ReplaceNoCase(qryCircuits.name, ".cfc", "", "one") />
  <cfset oCircuit = CreateObject('component',
    Replace(strControllerCircuitsPath, "/", ".", "all") & sCircuitName) />
  <cfset oMetaData = GetMetaData(oCircuit) />
  <cfset aFunctions = oMetaData.functions />  <p>
    <strong>Name:</strong> #oMetaData.Name#<br />
    <strong>Hint:</strong> <cftry>#oMetaData.Hint#<cfcatch>[none]</cfcatch></cftry>
  </p>
  <table summary="fuses in the #qryCircuits.name# circuit">
    <caption>Fuses in the #sCircuitName# circuit</caption>
    <cfloop from="1" to="#ArrayLen(aFunctions)#" index="ndx">
      <cfif ListFindNoCase(lstHidefuses, aFunctions[ndx].name) eq 0>
      <tr>
        <th scope="col" colspan="2">
        #aFunctions[ndx].name# [#sCircuitName#.#aFunctions[ndx].name#]
        </th>
      </tr>
      <tr>
        <td class="property">hint:</td>
        <td><cftry>#aFunctions[ndx].hint#<cfcatch>[none]</cfcatch></cftry></td>
      </tr>
      <tr>
        <td class="property">description:</td>
        <td><cftry>#aFunctions[ndx].description#<cfcatch>[none]</cfcatch></cftry></td>
      </tr>
      <tr>
        <td class="property">access:</td>
        <td><cftry>#aFunctions[ndx].access#<cfcatch>[none]</cfcatch></cftry></td>
      </tr>
      <tr>
        <td class="property">output:</td>
        <td><cftry>#aFunctions[ndx].output#<cfcatch>[none]</cfcatch></cftry></td>
      </tr>
      </cfif>
    </cfloop>
  </table>
  <p><a href="##top">back to the top</a></p>
</cfloop>
</body>
</html>
</cfoutput>

<cffunction name="ControllerCircuits"
  returntype="query"
  hint="I return all the cfc's in the specified directory">
  <cfargument name="ControllerCircuitPath"
    required="true"
    hint="I am the relative path to the Controller cfc files." />
  <cfset var strFullPath = ExpandPath(Arguments.ControllerCircuitPath) />
  <cfif ReFind("(\.){2}(\/|\\)", Arguments.ControllerCircuitPath)>
    <cfthrow message="'#Arguments.ControllerCircuitPath#' invalid. You can not navigate up."
      detail="Please specify a directory beneath #GetDirectoryFromPath(GetCurrentTemplatePath())#" />
  <cfelseif DirectoryExists(strFullPath)>
    <cfdirectory action="list"
      directory="#strFullPath#"
      filter="*.cfc"
      name="qryControllerCircuits" />
  <cfelse>
    <cfthrow message="The specified directory does not exists"
      detail="directory '#strFullPath#' does not exists." />
  </cfif>
  <cfreturn qryControllerCircuits />
</cffunction>

No Comments Yet »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.