Question
· Feb 16

%Library.PropertyHelper not accepting variable

*** updated from a comment as original question may not have been clear**

To clarify my question this is the library property helper class Library property helper when you look at the documentation for computed from documentation here Computed documentation

ClassMethod FullNameComputation(cols As %Library.PropertyHelper) As %String
{
    return cols.getfield("FirstName")_" "_cols.getfield("LastName")
}
// ...

 

ClassMethod RecordsComputation(cols As %Library.PropertyHelper) As %Library.ListOfDataTypes
{
  Set rsTProp = ##class(%SQL.Statement).%ExecDirect(,"Select * from Data_Clinicom.TransactionProperties where TransactionType='"_cols.getfield("TransactionType")_"' and IgnoreOnBuild is null ORDER BY RecordNumber asc, SequenceInRecord asc")
     While rsTProp.%Next() 
    {
    set property = rsTProp.PropertyName
    set data = cols.getfield(property)
    }
    .... further code it does retrun data
    }

 

 

In code though in my code using a variable to pass in isn't working and results in 

Records': 'FIELD: ropert, CODE:    set cols.fields("ropert")={ropert}'

The following code also doesn't work 

set p="Sex"
set data = cols.getfield(p)

The following would work but i need the variable 

set data = cols.getfield("Sex")

Any ideas?

**Original Wording below**

Trying to run the SQLComputed code and running into an issue with my idea. 

I have a property for instance called Sex

set data = cols.getfield("Sex")

This works. 

the following errors 

set property="Sex"

set data = cols.getfield(property)

If you try to pass it by variable data you get 

Records': 'FIELD: ropert, CODE:    set cols.fields("ropert")={ropert}'

I've tried every idea i think of , $Gets ect appending on values ect. Can't figure it out

Product version: IRIS 2023.1
Discussion (9)2
Log in or sign up to continue

To clarify my question this is the library property helper class Library property helper when you look at the documentation for computed from documentation here Computed documentation

ClassMethod FullNameComputation(cols As %Library.PropertyHelper) As %String
{
    return cols.getfield("FirstName")_" "_cols.getfield("LastName")
}
// ...

But you can't seem to throw a parameter i.e.par= "Firstname" cols.getfield(par) in the code without it throwing errors

This is interesting.

It is evident that when the class is compiled IRIS parse the <PropertyName>Computation() method(s) to find out what properties are actually used/referenced/passed to the cols.getfield() method(s), then it use this information to set the "fields" multidimensional property of %Library.PropertyHelper class before calling the <PropertyName>Computation() method.
This way only the used properties are set in the "fields" multidimensional property of %Library.PropertyHelper class.
This optimization improves performance in case of a class with many properties, possibly "complex" properties (calculated, references etc.) and I believe this is why has been implemented.

The "parser" is...simple, very simple.

To prove this assumption I wrote a little sample:

Class Community.Computation Extends %Persistent
{

Property FirstName As %String;
Property LastName As %String;
Property FullName As %String [ SqlComputed ];
ClassMethod FullNameComputation(cols As %Library.PropertyHelper) As %String
{
    ; cols.getfield("FirstName")
    ; cols.getfield("LastName")
    return ..FullNameComputationSub(cols,"FirstName","LastName")
}

ClassMethod FullNameComputationSub(cols As %Library.PropertyHelper, p1 As %String, p2 As %String) As %String
{
    return cols.getfield(p1)_" "_cols.getfield(p2)
}

/// do ##class(Community.Computation).test()
ClassMethod test()
{
    set obj=..%New()
    set obj.FirstName="Enrico"
    set obj.LastName="Parisi"
    write obj.FullName,!
}

}

If I run test() I get:
 

do ##class(Community.Computation).test()
Enrico Parisi

If I remove the commented line "; cols.getfield("FirstName")" and run test() again:

do ##class(Community.Computation).test()
 Parisi

If you look at your error:

"set cols.fields("ropert")={ropert}'"

That's the parser that found "cols.getfield(property)" and assuming a string was passed removed the first and last characters (assuming were double quotes), so it got "ropert".

Bottom line, cols.fields() can only be used passing a string constant with a property name.

There arises two questions.

First, why do you use a class where the documentation starts with "This class is used internally to hold property/field values needed for computed fields"?
Another word for classes which are marked as "used internally" is, that this classes can be changed (altered in its behavior) without any notice or documentation in one of the next versions. That's definitelly not what you want.
 
Second, what is your real problem (where you think, it's only solvable by using that %Library.PropertyHelper class)? Can you post (and describe) your real problem?

Well Julius, in general I would agree with you under that circumstances, BUT, in this particular case, the code he has implemented correspond exactly to the "Defining a Computed Property" documentation sample.

This is not a case of using %Library.PropertyHelper in random code, it's a case of using it according to documentation.

Granted that he is trying to use a variable instead of a string constant and (for good reasons IMO) does not work due of implementation constraints.

I agree that understanding the actual requirements and what needs to be implemented (the real problem), a viable solution can be suggested.

Thanks:

Over the weekend a viable solution has been found for this. A decision was made that actually the code being ran was probably too complex to be a computed field. This code was originally written in a Business process. The solution was to amend the custom method of the process and call a classmethod for this which could be run in a dtl or when setting up the class. 

The scenario was we had a property that is a long string of all the other values 

Decided best just to add to any DTL 

I would prefer it generating the function when the dtl is complete ect in the class without having to call it externally but i doubt it is actually possible