My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
A common problem I've been having and seeing lately is dealing with components that should read files in locations they don't know about. For instance, you have component Model in cfrails, which should read a configuration file in the project that is using it. I didn't want to have to create a mapping for every project, and I didn't want to have to figure out the ../../../../etc between the two directories to pass the value in to Model. So, here's a function which takes care of the mapping for you. If you needed, it would be trivially easy to add a new parameter for base template, if you didn't want to use the actual base template as your basis for inclusion.

It doesn't have any associated automated tests, mainly because I can't figure out how I'd test something like this. So, I tested it manually in 3 different directory structures, and it works fine for me. If you ever find a need for this, and encounter problems, I'd like to know about it - especially the directory structures your using so I can replicate and fix it.

So, without further ado, here's the code:

<cffunction name="includeRelativeToBaseTemplate" description="Given the current template's path, includes a file relative to the base template path" output="true" access="private">
<!---
   why ?
   Because sometimes, even though the "current template path" is known from getCurrentTemplatePath,
   cfinclude appears to use it's _actual_ current template. For example, you have
   A.cfc in dir1, and B.cfc, which extends A.cfc, but it resides in another directory. But, you
   want to cfinclude a file within A.cfc relative to the file that instantiated B.cfc. Well, I didn't
   find it very simple, so I created this function. =)
--->

   <cfargument name="currentTemplate" hint="The template which should be relative to.">
   <cfargument name="relativePath" hint="The relative path to the include, from the base template.">

   <cfset var local=structNew()>

   <cfset local.baseTemplate = getBaseTemplatePath()>
   <cfset local.curTemplate = arguments.currentTemplate>       <cfset local.relative=arguments.relativePath>
         
   <!--- in case of unix, convert slashes --->
   <cfset local.baseTemplate = replace(local.baseTemplate,"\","/","all")>
   <cfset local.curTemplate = replace(local.curTemplate,"\","/","all")>
         
   <cfloop from="1" to="#max(listlen(local.baseTemplate,'/'),listlen(local.curTemplate,'/'))#" index="local.i">

      <cfset local.baseDir=listGetAt(local.baseTemplate,local.i,"/")>
      <cfset local.curDir=listGetAt(local.curTemplate,local.i,"/")>
      <cfif local.baseDir neq local.curDir>
         <cfbreak>
      </cfif>
   </cfloop>   
      
   <cfset local.goBackTimes=listlen(local.curTemplate,'/')-local.i>
   <cfset local.dotDotSlash = repeatString("../", local.goBackTimes)>
   <cfset local.newPath=listDeleteAt(local.baseTemplate,listLen(local.baseTemplate,"/"),"/")>
         
   <cfloop from="1" to="#local.i-1#" index="local.k">
      <cfset local.newPath = listDeleteAt(local.newPath,1,"/")>
   </cfloop>
         
   <cfif listlen(local.baseTemplate,'/') lt listlen(local.curTemplate,'/')>
      <cfset local.dotDotSlashesInRelative = listvaluecount(local.relative,"..","/")>
      <cfloop from="1" to="#local.dotDotSlashesInRelative#" index="local.k">

         <cfset local.newPath = listDeleteAt(local.newPath,listLen(local.newPath,"/"),"/")>
      </cfloop>
      <cfset local.relative = replace(local.relative,"../","","all")>
   </cfif>
   
   <cfset local.newPath = local.dotDotSlash & local.newPath & "/" & local.relative>
   
   <!---if fileExists(expandPath(local.newPath)) - cf using different relative path than current? --->
   <cftry>
      <cfinclude template="#local.newPath#">

      <cfset result = true>
      <cfcatch>
         <cfset result = false>
      </cfcatch>
   </cftry>
   <cfreturn result>
</cffunction>



Hey! Why don't you make your life easier and subscribe to the full post or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!


Comments
Leave a comment

There are no comments for this entry yet.

Leave a comment

Leave this field empty
Your Name
Email (not displayed, more info?)
Website

Comment:

Subcribe to this comment thread
Remember my details
Google
Web CodeOdor.com

Me
Picture of me

Topics
.NET (19)
AI/Machine Learning (14)
Answers To 100 Interview Questions (10)
Bioinformatics (2)
Business (1)
C and C++ (6)
cfrails (22)
ColdFusion (78)
Customer Relations (15)
Databases (3)
DRY (18)
DSLs (11)
Future Tech (5)
Games (5)
Groovy/Grails (8)
Hardware (1)
IDEs (9)
Java (38)
JavaScript (4)
Linux (2)
Lisp (1)
Mac OS (4)
Management (15)
MediaServerX (1)
Miscellany (76)
OOAD (37)
Productivity (11)
Programming (168)
Programming Quotables (9)
Rails (31)
Ruby (67)
Save Your Job (58)
scriptaGulous (4)
Software Development Process (23)
TDD (41)
TDDing xorblog (6)
Tools (5)
Web Development (8)
Windows (1)
With (1)
YAGNI (10)

Resources
Agile Manifesto & Principles
Principles Of OOD
ColdFusion
CFUnit
Ruby
Ruby on Rails
JUnit



RSS 2.0: Full Post | Short Blurb
Subscribe by email:

Delivered by FeedBurner