The simplicity of Lucee
Four years ago I listed various new features in ColdFusion 9 which helped simplify my code, as compared to the previous version 8.
Having recently migrated from CF9 to Lucee, I thought I'd repeat the exercise. So here are some of the features of Lucee which I'm finding help make my code simpler to write and understand.
(Note: I know many of the following are available in more recent versions of Adobe ColdFusion. Simplicity is relative, and the comparison here is between Lucee 4.5 and ACF 9.0.1).
Query loops in script
ColdFusion 9
for( i=1; i LTE myQuery.recordcount; i++ ){
WriteOutput( myQuery.ID[ i ] & "<br/>" );
}
Lucee
for( row in myQuery ){
Echo( row.ID & "<br/>" );
}
Built-in Functions
DateTimeFormat()
ColdFusion 9
date = Now();
WriteOutput( DateFormat( date,"dddd, d mmmm yyy" ) & ", " & TimeFormat( date,"HH:mm:ss" ) );
Lucee
date = Now();
Echo( DateTimeFormat( date,"EEEE, d mmmm yyy, HH:nn:ss" ) );
Note that the full day of the week name (e.g. Wednesday) mask is EEEE
in Lucee and not dddd
, which seems to return the day of the month with leading zeros.
Update 25 April 2015: The minute mask is different from TimeFormat()
and should be nn
not mm
as originally posted.
Echo()
See examples above. To be honest, I was briefly resistent to the PHP-esqueness. WriteOuput()
is more descriptive, but this a function I use a lot when testing and for frequently used code, brevity may trump clarity when it comes to simplification.
Dump()
ColdFusion 9
WriteDump( server );
Lucee
Dump( server );
IsEmpty()
ColdFusion 9
myString = "";
WriteDump( !Len( myString ) ); //-> TRUE
Lucee
myString = "";
Dump( IsEmpty( myString ) ); //-> TRUE
NullValue()
ColdFusion 9
myNull = JavaCast( "Null","" );
Lucee
myNull = NullValue();
GetCanonicalPath()
This function comes in handy when building file paths dynamically from several parts which may or may not be relative or have leading/trailing slashes. For example, we might need to build the path C:\a\2\tests\test.txt
as:
path = "C:\a\1\";
path &= "../2/";
path &= "/tests/";
path &= "test.txt";
WriteDump( path );
This outputs the rather messy C:\a\1\../2//tests/test.txt
.
In Lucee we can clean this up:
Dump( GetCanonicalPath( path ) );
Which outputs: C:\a\2\tests\test.txt
.
My only reservation about this function is that it reverses forward-slashes on Windows. Other OSes use forward slashes and since they work fine on Windows too that should be the default, not back-slashes, to keep things platform-agnostic.
DirectoryCopy()
No more intermediate zipping!
ColdFusion 9
<cfscript>
sourcePath = ExpandPath( "./test" );
destinationPath = ExpandPath( "./testCopy" );
tempZipPath = "ram:///#CreateUUID()#.zip";
if( !DirectoryExists( destinationPath ) )
DirectoryCreate( destinationPath );
</cfscript>
<cfzip
action="zip"
source="#sourcePath#"
file="#tempZipPath#"
recurse="true"
storepath="true"/>
<cfzip
action="unzip"
file="#tempZipPath#"
destination="#destinationPath#"
storePath="yes"
overwrite="yes"/>
<cffile action="delete" file="#tempZipPath#">
Lucee
sourcePath = ExpandPath( "./test" );
destinationPath = ExpandPath( "./testCopy" );
DirectoryCopy( sourcePath,destinationPath,true,"",true );
Note the final optional argument of DirectoryCopy()
causes the destination path to be created if it doesn't exist.
Miscellaneous
Null coalescing (Elvis) operator
As I was refactoring the old Railo Spreadsheet extension into my Lucee Spreadsheet Library, the perfect job for the Elvis operator came up.
A struct of spreadsheet "info" needed to be transferred from POI to CFML but without any java nulls where a value didn't exist. The old code tackled each value as follows:
value = coreProps.getCreator();
info.author = IsNull( value )? "":value;
With the help of Elvis this could be shrunk to:
info.author = coreProps.getCreator()?:"";
Member functions
The IsEmpty()
example above is not written the way I'd actually use it. Instead I'd call the function as if the empty string variable were an object and IsEmpty()
one of its methods:
myString = "";
Dump( myString.IsEmpty() );// ->TRUE
Not all functions support this type of "Member functionality", so it's important to check the documentation and test.
The one I find I'm using and appreciating most so far replaces StructKeyExists()
, which I've always disliked having to type:
ColdFusion 9
WriteDump( StructKeyExists( myStruct,"myKey" ) );
Lucee
Dump( myStruct.KeyExists( "myKey" ) );
Tags in script
Although I still believe tags have their place in certain limited cases, I've preferred using cfscript where its capability has allowed ever since it was introduced in ColdFusion 4.0.
Questions have been raised about the way "tags in script" have been implemented, but just being able finally to use the following in particular without dropping out of script and into tags, or down to unsupported Java methods, is a delight.
<cfcontent>
<cfcookie>
<cfexecute>
<cfheader>
<cfpdf>
<cfsetting>
Server wide pageEncoding
Finally, ever since I became aware of encodings/charsets and their impact many years ago, I've been putting the following at the top of each and every ".cfm" and ".cfc" file I create to ensure any "special" characters I might type—such as £—are displayed correctly.
<cfprocessingdirective pageencoding="utf-8"/>
With Lucee this is no longer necessary as the "template charset" can be specified globally in the admin, either at the server or individual "web context" level.
Comments