Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic Type Conversion in ColdFusion 11

Tags:

coldfusion

I am migrating an application from ColdFusion 9 to ColdFusion 11.

In the existing code there is an assignment of a variable to false:

<cfset VARIABLES.roleTypeId = false >

And then, farther down, a function that expects this variable to be numeric:

<cffunction name="rolesForStudy" >
    <cfargument name="id" hint="Study Id">
    <cfargument name="roleTypeId" default="#VARIABLES.roleTypeId#" type="numeric"/>
</cffunction>

I inherited the code, and I cannot defend the original programmer's decision to set it up this way -- but, in short, it worked in ColdFusion 9, and it doesn't work in ColdFusion 11 (returning a data type error). I assume that ColdFusion 9 was automatically converting false to 0.

My question: Is there a configuration setting that I can change in ColdFusion 11 to make it do the conversion like ColdFusion 9 did? Or will I have to fix this code, along with probably lots of other similar examples throughout the application? Neither I nor our ColdFusion administrator has been able to find any information about this in the ColdFusion Administrator interface, the ColdFusion documentation, or online.

Edit in Response to Adam Cameron in comments

I have created a file that consists of the following 10 lines (and nothing else):

<cfset VARIABLES.roleTypeId = false >
<cfoutput>
<p>#rolesForStudy( 1, VARIABLES.roleTypeId )#</p>
</cfoutput>

<cffunction name="rolesForStudy" >
    <cfargument name="id" hint="Study Id">
    <cfargument name="roleTypeId" default="#VARIABLES.roleTypeId#" type="numeric"/>
    <cfreturn "It worked" >
</cffunction>

When I execute it in ColdFusion 9, it displays the words "It worked".

when I execute it in ColdFusion 11, it returns the following error message:
If the component name is specified as a type of this argument, it is possible that either a definition file for the component cannot be found or is not accessible.

like image 642
Joe DeRose Avatar asked Dec 12 '14 16:12

Joe DeRose


3 Answers

I believe you will have to fix the code. There are no settings (that I know of at any rate) that alter the way CF handles boolean types. You should be able to change the assignement above from "false" to 0 and your function code will work. However I suspect elsewhere you might have something like <cfif variables.roletypeID IS "False"> which will then be broken as it is in truth looking for a string - which also works (ha). CF's handling of a myriad of values as boolean (0 or not 0, true, false, yes and no) is a legacy of it's origin. It's convenient at times but definitely leads to things like this.

Meanwhile I wonder if this change of behavior is a new bug or the fixing of an old bug. In my view passing "false" as an argument and having it read as numeric seems inconsistent so the new way of doing it seems right to me. However, many many languages treat 0 or not 0 as default values for true and false.

EDIT:

According to Adam's comments below, my example of code where someone would say:

<cfif somevar IS "false">

...would work even if somevar was indeed numeric. His example (useful) is that:

#0 is "False"#

...will output "yes" - so CF is recasting the string "false" to a zero under the hood for comparison. That makes my example incorrect.

My answer is still correct I believe. The issue he's running into is that the argument passed to his function - being of the type "boolean" is throwing an error because the function expects a numeric value. But Adam's point and example makes me think perhaps this behavior is a bug - since it appears CF is not casting to a number before checkign the type (something it did do in CF 9 according to the Joe).

like image 117
Mark A Kruger Avatar answered Dec 13 '22 23:12

Mark A Kruger


NumberFormat is your saviour, credit going to this comment on one of Ben Nadel's articles.

<cfset VARIABLES.roleTypeId = false>
#NumberFormat(VARIABLES.roleTypeId)# <!-- = 0 -->
<cfset VARIABLES.roleTypeId = true>
#NumberFormat(VARIABLES.roleTypeId)# <!-- = 1 -->

So you should be able to either convert it to the expected numeric type before calling the function, or just doing

<cfargument name="roleTypeId" default="#NumberFormat(VARIABLES.roleTypeId)#" type="numeric">
like image 25
duncan Avatar answered Dec 13 '22 23:12

duncan


I've raised this as a bug in ColdFusion 11: "Type coercion failure when passing boolean to a numeric arg".

I recommend you work around this by taking the type check off the argument. This is probably the lowest-impact fix.

This is also a rare case in which I'd add a comment to code, explaining why you've taken the type checking off.

Apologies to Joe, Mark & Duncan for emphatically contradicting what they were finding. That said, I don't agree that their answers are the best approach here ;-)

like image 20
Adam Cameron Avatar answered Dec 13 '22 23:12

Adam Cameron