I am trying to do this
<cfset noncooperativevariable = #serverfile#>
and I get a serverfile not defined error. When I try to use the correct variable scope
<cfset noncooperativevariable = #CFFILE.serverfile#>
which returns the error.
You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members.
Edit:
<cffile action="upload" filefield="fileUpload" destination="#destination#" nameConflict="makeUnique" result="upload">
<cfset noncooperativevariable = #fileUpload.serverfile#>
When using the cffile tag, the results are defaulted to the cffile struct in your Variables scope. Therefore, if you are uploading a file with the following code:
<cffile action="upload" filefield="fileUpload" destination="#destination#" nameConflict="makeUnique" />
The results are accessible via the cffile struct in your Variables scope. The filename would be referenced as follows:
<cfset cooperativeVariable = cffile.serverfile />
In the snippet posted, you are using the 'result' attribute which would place your cffile results in the struct named upload instead of cffile, so you would get the filename like so:
<cfset cooperativeVariable = upload.serverfile />
Related
I tried to rewrite my Application.cfc and other .cfc files in my system with cfscript. There is few things that I'm not sure how they work in cfscript. I'm wondering about defining variables inside of the functions. For example onRequestStart() function looks like this:
function onRequestStart(required string thePage) returntype="boolean" output="false" {
var request.appCode = "MyApp";
var request.appName = "Single Page Application";
var page = listLast(arguments.thePage,"/");
var onApplicationStart();
if(!listFindNoCase("Home.cfm,Auth.cfc",page)){
if(structKeyExists(SESSION, "loggedin") AND SESSION.loggedin EQ false){
location(url="https://www.myapp.org", addToken="false");
}
}
return true;
}
Do I need to use var word in situations where I'm defining request/session variables? If I do what is the best practice, use var word or use local.variablename? Is local and variables same in cfscript?
var is used only for local variables. That means variables which are/should not be accessible outside the function definition. Session & Request are accessible to each session & request respectively. Putting them on var scope will give terrible results.
You can use either var or local, both have 'local' scope. Variables is the page scope and any variable defined in the Variables scope will be accessible to all functions in the CFC.
function onRequestStart(required string thePage) returntype="boolean" output="false" {
request.appCode = "MyApp";
request.appName = "Single Page Application";
var page = listLast(arguments.thePage,"/");
//this is a function call and not variable declaration.
onApplicationStart();
if(!listFindNoCase("Home.cfm,Auth.cfc",page)){
if(structKeyExists(SESSION, "loggedin") AND SESSION.loggedin EQ false){
location(url="https://www.myapp.org", addToken="false");
}
}
return true;
}
var is not equal to the <cfset> tag, i.e. you can't do a simple search & replace when switching to CFScript syntax.
var is only used for local variable definitions. This means, setting structure and array items, like request, session and other scope variables should not be prefixed by var.
Also, function calls must be written without preceding var.
local and var both refer to the local scope. Though note, as mentioned above, if you want to define variables via local.something the var keyword is also not needed.
variables, in contrary to local, refers to the page scope, which is accessible from everywhere within the component and any included pages.
For more info on the different scopes, you should read the Adobe docs.
my BuildParameter is defined in my xaml build as follows:
<Activity this:Process.AdvancedBuildSettings=
"[New Microsoft.TeamFoundation.Build.Common.BuildParameter(
" { ""Attribute1"": """",
""Attribute2"": ""Value2"",
""Attribute3"": ""Value3"" } "
)]">
Now I want to update the value of Attribute1 of my BuildParameter but I can't figure out how to do it.
It doesn't look like I can use an Assign block because these attributes names are not known by the compiler, so I want to use BuildParameter's SetValue method but I'm not sure how to call this VB code in my xaml.
<Assign DisplayName="Update That Attribute">
<Assign.To>
<OutArgument x:TypeArguments="x:String">[AdvancedBuildSettings.Attribute1]</OutArgument><!-- this throws a compiler error because it doesn't know what Attribute1 is -->
</Assign.To>
<Assign.Value>
<InArgument x:TypeArguments="x:String">""NewValue""</InArgument>
</Assign.Value>
</Assign>
Not familiar with XAML, but here is a code snippet that using TFS API in C# to update the parameter name. You can use WorkflowHelpers.DeserializeProcessParameters Method and WorkflowHelpers.SerializeProcessParameters Method to get parameter name, remove it, and add the new parameter name, maybe it can help you something:
string argumentName = "Attribute1";
var process = Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers.DeserializeProcessParameters(BuildDefinition.ProcessParameters);
if (process.ContainsKey(argumentName))
{
process.Remove(argumentName);
process.Add(argumentName, attributeValue);
BuildDefinition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process);
BuildDefinition.Save();
}
I was right, the "Assign" workflow tool was not the tool I wanted. I needed to use the "InvokeMethod" workflow tool in order to invoke the SetValue() method of my BuildParameter object in my XAML build.
MSDN InvokeMethod documentation
More details about the properties of InvokeMethod
So my solution looks like this:
<InvokeMethod DisplayName="Invoke That Method" MethodName="SetValue">
<InvokeMethod.GenericTypeArguments>
<x:Type Type="x:String" />
</InvokeMethod.GenericTypeArguments>
<InvokeMethod.TargetObject>
<InArgument x:TypeArguments="mtbc:BuildParameter">[AdvancedBuildSettings]</InArgument>
</InvokeMethod.TargetObject>
<InArgument x:TypeArguments="x:String">Attribute1</InArgument>
<InArgument x:TypeArguments="x:String">[NewValue]</InArgument>
</InvokeMethod>
I have a list of variables' suffixes such as: "mono", "uni", "kid"
These should be appended to a variable name (bike_) and used such as:
${item.bike_mono!}
${item.bike_uni!}
${item.bike_kid!}
I tried playing around with the freemarker's interpret built-in but no success.
You can use square brackets to access them. So if your object looks like this
Map<String, String> item = new HashMap<>();
item.put("bike_mono", "Mono");
item.put("bike_uni", "Uni");
item.put("bike_kid", "Kid");
model.addAttribute("item", item);
Your template can access it like this
<#assign suffixes=["mono", "uni", "kid"]>
<#assign prefix="bike_">
<#list suffixes as suffix>
${item[prefix+suffix]!}
</#list>
My question is probably best illustrated with an example. In javascript I'm used to being able to do stuff like this:
// create a simple class
function myClass() {
this.attr_example = "attribute";
}
myClass.prototype.do_something = function() {
return "did something";
}
// create an instance of it, and modify as needed
var thing = new myClass();
thing.myMethod = function(arg) {
return "myMethod stuff";
}
// ... so that this works as expected
console.log(thing.myMethod());
console.log(thing.do_something());
console.log(thing.attr_example);
When it comes to doing something similar in ColdFusion, I get stuck. I constantly find myself wanting to do things like this:
<cfscript>
// thing.cfc contains a normal cfcomponent definition with some methods
var thing = createObject("component","Thing");
function formattedcost() {
return "#LSCurrencyFormat(this.cost)#";
}
thing.formattedcost = formattedcost;
</cfscript>
<cfoutput>
#thing.formattedcost()#
</cfoutput>
Let's assume that for this question, it doesn't make sense to add "formattedcost" as a method on the Thing class because it is purely presentational. Let's also assume that simply using #LSCurrencyFormat(thing.cost)# in the <cfoutput> tags wont suffice either because we need the instance of Thing to be evaluated by a templating system (mustache in this case). Even further, I'd like to avoid having to create another .cfc file just to extend my Thing class to add a couple of methods.
What can I do? Is this style of programming possible in ColdFusion?
Yes you can do this:
Thing.cfc
<cfcomponent output="false" accessors="true">
<cfproperty name="cost" type="numeric">
<cffunction name="init" output="false" access="public"
returntype="any" hint="Constructor">
<cfargument name="cost" type="numeric" required="true"/>
<cfset variables.instance = structNew()/>
<cfset setCost(arguments.cost)>
<cfreturn this/>
</cffunction>
</cfcomponent>
test.cfm
<cfscript>
// thing.cfc contains a normal cfcomponent definition with some methods
thing = new Thing(725);
function formattedcost() {
return "#LSCurrencyFormat(getCost())#";
}
thing.formattedcost = formattedcost;
</cfscript>
<cfoutput>
#thing.formattedcost()#
</cfoutput>
Result
$725.00
I'm looking at securing a low level object in my model (a "member" object) so by default only certain information can be accessed from it.
Here's a possible approach (damn sexy if it would work!):
1) Add a property called "locked" - defaulting to "true" to the object itself.
It appears that the only option to do this, and not tie it to a db table column, is to use the formula attribute that takes a query. So to default locked to TRUE I've got:
<cfproperty name="locked" formula="select 1" />
2) Then, I overwrite the existing set-ers and get-ers to use this:
e.g.
<cffunction name="getFullname" returnType="string">
<cfscript>
if (this.getLocked()) {
return this.getScreenName();
} else {
return this.getFullname();
}
</cfscript>
</cffunction>
3) When i use it like this:
<p> #oMember.getFullName()# </p>
shows the ScreenName (great!)
but... When I do this:
<cfset oMember.setLocked(false)>
<p> #oMember.getFullName()# </p>
Just hangs!!! It appears that attempting to set a property that's been defined using "formula" is a no-no.
Any ideas? Any other way we can have properties attached to an ORM object that are gettable and settable without them being present in the db?
Ideas appreciated!
Any other way we can have properties
attached to an ORM object that are
gettable and settable without them
being present in the db?
Yes,
<cfproperty name="locked" persistent=false>
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSB7BEC0B4-8096-498d-8F9B-77C88878AC6C.html
Is it because in the else statement of your function, you are calling the same function name again? So its just recurring.
Try renaming the function name so its not overriding the implicit getter and see what happens. For example
<cffunction name="getNewname" returnType="string">
<cfscript>
if (this.getLocked()) {
return this.getScreenName();
} else {
return this.getFullname();
}
</cfscript>