Monday, 31 March 2014

CFML: Survey follow-up (no results yet sorry): need some more input

G'day:
I realise it's not a very exciting survey, but my recent "Survey: lists in CFML, and the naming of list member functions" isn't getting an amount of attention that makes it meaningful for me to report on. I will be writing up the results - whatever they are - tomorrow anyhow, but it'd be good if you could put your oar in between now and then. If you haven't already, I mean.

The direct link to the survey is thus: "List function support as member functions in CFML".

Cheers!

--
Adam

Sunday, 30 March 2014

Open Letter to site admins I might be contacting in the near future about the security of your ColdFusion site

Hi:
If you are reading this article, it's probably down to one of two reasons:
  1. you're one of my regular blog readers, in which case this will have just found its way in front of you just like anything else I write;
  2. you are a person I have successfully contacted who - hopefully - the administrator of a ColdFusion-driven website that I have noticed as having some security issues.
The article is targeted at the second group of people. If I have contacted you directly, it is vitally important you read this, and follow-up on it.

How about this for savecontent?

G'day:
The approach that CFML has taken for the CFScript implementation of <cfsavecontent> has always annoyed me, because it doesn't follow the normal syntax for doing processing and returning a result. Plus there was the need to add a new syntax construct as well. It's just occurred to me that this was not necessary. A simple function would have done the trick.


To contextualise things, let's have a look at the <cfsavecontent> tag:

<cfset days = ["Rāhina","Rātū","Rāapa","Rāpare","Rāmere","Rāhoroi","Rātapu"]>
<cfsavecontent variable="contentViaTags">
<ul>
<cfloop index="day" array="#days#">
    <cfoutput><li>#day#</li></cfoutput>
</cfloop>
</ul>
</cfsavecontent>
<cfoutput>#contentViaTags#</cfoutput>

I'm just capturing the output from some simple CFML processing there, and then outputting it. It's a dumb usage of <cfsavecontent>, but it demonstrates it OK. The syntax here is entirely reasonable, and completely clear as to what's going on. It's a handy tag.

ColdFusion and Railo had already both had a go at implementing this for CFScript. And both failed (well: they came up with the same solution):

savecontent variable="contentViaScript" {
    writeOutput(days.reduce(function(previousResult, thisValue){
        return previousResult & "<li>#thisValue#</li>";
    },"<ul>") & "</ul>");
}
writeOutput(contentViaScript);

The problem here is twofold.
  1. CFML syntax for setting a variable to be the result of some processing is:
    variable = process
    Not:
    process variable="nameOfVariable"
    So it's at odds with out CFML works to approach functionality that way.
  2. We need to add this new {} syntax to enclose the code we're saving the output of. This is a new syntax construct implemented solely to emulate opening/closing tags. This is script code, so we should not be thinking in terms of opening and closing tags.
So that syntax is a loser IMO.

ColdFusion 11 has just managed to make this worse. Now we're going back to basically using tags:

cfsavecontent(variable="contentViaScriptNew") {
    writeOutput("<ul>");
    days.each(function(v){
        writeOutput("<li>#v#</li>");
    });
    writeOutput("</ul>");
}
writeOutput(contentViaScriptNew);

It also means we have two separate - and mostly the same but slightly different - constructs for doing a savecontent operation in CFScript. This is a double fail. How long will it be before we start forgetting which syntax takes the parentheses and the commas, and which just takes spaces?

But this is what's just occurred to me today. We never needed any special syntax at all to achieve savecontent in CFScript:

contentViaFunction = savecontent(function(){
    var decoratedDays = days.map(function(v){
        return "<li>#v#</li>";
    });
    writeOutput("<ul>#decoratedDays.toList('')#</ul>");
});
writeOutput(contentViaFunction);

It's just a function call. A plain old function call. We call the savecontent() function, it takes a callback which contains the code which we want to capture the output of, and returns that in its return value.

Isn't that a better approach than messing about with new syntax and weirdo ways of assigning values?

What's more... the implementation is piss-easy. It's just this:

function saveContent(required function content){
    savecontent variable="local.saved" {
        content();
    }
    return local.saved;
}

Obviously because I'm implementing this with CFML I need to reuse one of the other constructs, but it demonstrates what a simple concept to implement it is.

This is another example of what I mean that rather than taking a generic approach to implementing previously tag-only functionality in CFScript, it needs a bespoke approach. CFScript is now a first class citizen of CFML, and it deserves to have its functionality implemented carefully and thoughtfully. Not just in an automated/generic way that makes the life of the engineers and Adobe and Railo a bit easier.

I have added this suggestion as a comment on an existing Adobe ticket: 3643125;  and a new one for Railo: RAILO-3008.

--
Adam

ColdFusion 11: calling a stored procedure from script. And can we please stop wearing out our "c" and "f" keys?

G'day:
I'm not sure what's got into me today... I'm supposed to be completing a Backbone.js course @ Code School, but I keep finding things to look at in Railo / ColdFusion instead. This is the fourth article I've written this afternoon. And it's only 3pm.

I'm looking at two things in this article. Calling a stored procedure from CFScript, and how I really don't think our code needs to scream "cf" "cf" "cf" at us the whole time. We get it. It's a CFM file. It's got CFML in it. We don't also need every single line of code in it reminding us of this. But this is what we will have if Adobe get their way.

Railo: I've got to the bottom of that code I asked you to test for me

G'day:
Thanks to everyone who helped out with my challenge in this article: "Railo: help me replicate a bug I'm seeing on one of my machines". I think the reason I was seeing the difference in behaviour is twofold:
  1. I'm a dropkick;
  2. Railo's setting "Local scope mode" (which I can't find docs to link to [grumble], so I'll need to explain it).
The reason why I suspect I'm a dropkick is that I think this is all down to my machine at work having "local scope mode" set to "modern", whereas every other instance I have been looking at is set to "classic". I do not recall switching my work machine to use this setting (and I'll be switching it off as soon as I sit down at it on Monday), but it seems like this is what the difference is.

Thanks to Gert for pointing me in the direction of the various Railo "make Railo work differently from ColdFusion" settings that Railo has.

Railo: it already supports separating parameters from the SQL string

G'day:
This is a very quick  update to my previous article: "Query.cfc / queryExecute() have a good feature cfquery lacks". Railo already supports this (although it's apparently undocumented?).

Whilst raising the ticket for ColdFusion, I found an already-raised (and resolved) ticket in the Railo bugbase: RAILO-2203.

Micha has added a comment to the bottom of it: "added as hidden feature", but it is there and it does work:

<cfset params = [
    {value=URL.low},
    {value=URL.high}
]>
<cfquery name="numbersViaPositionalParams" params="#params#">
    SELECT  en AS english, mi AS maori
    FROM    colours
    WHERE   id BETWEEN ? AND ?
</cfquery>

<cfset params = {
    low=URL.low,
    high=URL.high
}>
<cfquery name="numbersViaNamedParams" params="#params#">
    SELECT  en AS english, mi AS maori
    FROM    colours
    WHERE   id BETWEEN :low AND :high
</cfquery>

Cool! Go Railo!

I shall update the ticket I raised with Adobe to encourage them to follow Railo's lead here.

--
Adam

Query.cfc / queryExecute() have a good feature <cfquery> lacks

G'day:
<cfquery> has been one of the mainstays of CFML for longer than I have been aware of CFML as a language. I presume it existed in some way, shape, or form in Cold Fusion 1.0. Up until ColdFusion 9, there was no way to perform a DB query in CFScript, unless one was to write a wrapper to do so. And I think we all had, at some stage or another.

Along came ColdFusion 9. It was during the development of ColdFusion 9 that Adobe first made the promise to implement all tag functionality in a scriptable way (note: it's taken them until CF11 to actually follow through on this promise), and when the first attempt at providing DB querying support in CFScript. I think it is astounding that it took until version 9 of the language before such a fundamental piece of functionality was available in CFScript, but there you go.