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>
Related
Custom boolean attributes do not bind like built in. checked.bind='1===2' will not include the checked attribute in the tag. myboolatt.bind='1===2' WILL include the myboolatt in the tag. I did myboolatt.bind='1===2 | boolconverter' to log out the value and it says false.
So what am I doing wrong? It seems Aurelia is inconsistent on binding expressions. Another instance is I can do this title=${$index<12} inside a repeat and I get what is expected. So I thought this would work - myboolatt.bind=${$index<12}. That doesn't even compile.
Believe me I have read the all the doc (doesn't mean I didn't miss something) and many posts including the long running discussions between the Aurelia team concerning boolean attributes.
I have wrapped expressions in "" and in ${} and in both but just can't get it to work.
It feels like I am missing 1 vital piece of information that will magically explain these inconsistencies and slay my frustration. One of the reasons I like Aurelia so much (on top of convention based) is that I have actually just guessed at a few things - thinking this is how I would do it - and ding-dang if they didn't just work.
I really feel like this should just work. So again I ask - what am I doing wrong?
Thanks
If you are using .bind, you bind it to the att variable in your js/ts file, and you should not use any dollar signs or brackets.
For example, myboolatt.bind=${$index<12} should be myboolatt.bind="$index<12". The use of the dollar sign in index has nothing to do with the bindings. This is just a variable provided by Aurelia.
When you want to use variables without bind you use ${variable}.
The checked attribute not being present, I in the tag I'm guessing is because it's evaluated to false, and the checked attribute is not a true/false attribute. A input that's checked will look like <input type="checkbox" checked/>
It was not Aurelia binding. I initially created bool attributes but did not have a need to bind. They were just empty classes. Then I needed binding so I added the necessary methods. What ended up causing the confusion was using myboolatt sends no argument into valueChanged where myboolatt.bind sends T or F. Not being a regular js'er this threw me a bit and I see there are a number of ways to handle. Anyway here are the attributes and usage. Hope it helps someone else.
Thanks
function private_ValueChanged(self, att, value) {
if (value === false) self.element.removeAttribute(att);
else self.element.setAttribute(att, '');
}
export class toggleCustomAttribute {
static inject = [Element];
constructor(element) { this.element = element; }
valueChanged(newValue, oldValue) { private_ValueChanged(this, 'toggle', newValue);
}
export class radioCustomAttribute {
static inject = [Element];
constructor(element) { this.element = element; }
valueChanged(newValue, oldValue) { private_ValueChanged(this, 'radio', newValue); }
}
<ff-button repeat.for="keymen of keyChangeMenu" radio.bind="$index<12" class='ff-button' click.delegate="keyChangeClick($event.target)" id.bind="$index+'_key'" >
${keymen[0]}<sup>${keymen[1]}</sup>
</ff-button>
I am using below snippet in html
value.two-way="lstName.IsBlocked ? 'Blocked' : Value2 + ' %'"
on console it shows error as
Uncaught Error: Binding expression
"lstName.IsBlocked?'Blocked':Value2+' %'" cannot be assigned to.
at b.a.assign (aurelia.js?v=1.0009:59)
at a.updateSource (aurelia.js?v=1.0009:61)
at a.call (aurelia.js?v=1.0009:61)
at a.v [as callSubscribers] (aurelia.js?v=1.0009:58)
at a.notify (aurelia.js?v=1.0009:60) `
What can be the reason for this ?
Thanks in advance!
Since you're using a two-way binding, the binding expression needs to be assignable.
As the error says: "lstName.IsBlocked?'Blocked':Value2+' %'" cannot be assigned to.. If your bound property changes from the view, it would have to be able to write back to the expression and update the source value in your view model. You can't really write to an inline if.
Change two-way to to-view and it should work.
EDIT:
Since you need the expression to be writable, you could use a ValueConverter to solve the problem (assuming Value2 is what you want to write to):
export class BlockedValueConverter {
toView(value, isBlocked) {
return isBlocked ? 'Blocked' : value + ' %';
}
fromView(value) {
return value;
}
}
Then in your html (don't forget to require the valueConverter or use globalResources):
value.two-way="Value2 | blocked:lstName.IsBlocked"
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>
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
Now. I so confuse when use any classes. What is best practice approach to use them?
Example
I have a UserClass name User that have 2 attributes UserName and Password
when I use I will create new object like this
UserClass userObject = new UserClass();
this is my question that I so confuse to use
If i want to call Method name "Login" what is appropriate way to use them?
Between
1 Set Value to Attribute of Object Like this
userObject.UserName = "user";
userObject.Password = "password";
if (userObject.Login())
{
//Do Something After Login
}
else
{
//Show Something when Error
}
2 Send Value as parameter
if (userObject.Login("user","password"))
{
//Do Something After Login
}
else
{
//Show Something when Error
}
From above
What is appropriate approach to use and apply to any classes?
Thank you very much for your guidance _/\_
P.S I practice to be better Programmer
Use a property to store information that belongs to the object. (eg, a Username)
Use a parameter to pass information to a single method which doesn't have to do with the rest of the object.