#Object Data Model

4 Followers · 498 Posts

An object data model is that data or code is composed of modules that combine data and procedures that work on the data.

Learn more.

Question Joel Solon · Feb 18, 2016

This morning on the old Caché Google Group, someone posed the following question, which I've decided to answer here, because it's interesting!

Is there a way to iterate ClassMethod's params, and get param's names and values?

The first answer I can come up with is: it's not easy! In any method, you could try to write code like this (where methodName is the name of your method):

    set method = ##class(%Dictionary.MethodDefinition).IDKEYOpen($classname(), methodName)
    set args = method.FormalSpec
    for i=1:1:$length(args, ",") {
        set arg = $piece($piece(args, ",", i), ":", 1)
        write !, arg , " = ",  @arg
    }
1
1 1977
Question Peter Steiwer · Dec 12, 2016

Is there a better way to iterate through all properties of an object than the following? Perhaps without needing to open a definition of the class but directly against the object?


SAMPLES>set t=##class(HoleFoods.Transaction).%OpenId(1)                          
SAMPLES>set def=##class(%Dictionary.ClassDefinition).%OpenId("HoleFoods.Transaction")
SAMPLES>for i=1:1:def.Properties.Count() {  w def.Properties.GetAt(i).Name_":"_$property(t,def.Properties.GetAt(i).Name),!  }
Actual:0
AmountOfSale:4.95
Channel:2
Comment:
DateOfSale:62373
Discount:0
Latitude:
Longitude:
Outlet:35@HoleFoods.Outlet
Product:37@HoleFoods.Product
TargetAmount:
UnitsSold:1
ZipCode:
6
1 3591
Question Iryna Mykhailova · Nov 9, 2022

Hi guys!

My student asked my why his unit tests don't work as they should, and I just could answer him. Here is the simplified case.

There is a class with a required unique property Name:

ClassPropertyAs

And there is an inherited class:

%Persistent

What I expect to happen, is when I save two objects of class  with the same value of property Name, for the second one to get an error stating that it violates the unique index.

 ##class

 Right now, it saves both objects without any problems. And there's no index global as well.

9
0 806
Question Nic Lorenzen · Feb 28, 2016

Hello everyone!

Does anyone know of a library that can be used to create Mock objects for Objectscript classes?

Right now, my team has been building mock objects by hand to help circumvent dependencies when writing and executing unit tests, but I always wondered if someone had ever created a Mock library like Mockito to help quicken the process. 

Thanks!

4
0 1203
Question Alexey Maslov · Jun 14, 2018

I am still working on a generic task where I need to apply journal file records to another database. Initially I didn't want to use Journal.Restore class methods as I need to perform some data transformation, and it seemed that the clearest way to achieve it was to read journal file record by record using %SYS.Journal.Record API. 

This approach worked (with some help from @Dmitry Konnov Maslennikov and @Eduard Lebedyuk), while it turned that the processing speed of %SYS.Journal.Record:List query was very slow, about 1MB of journal data per second on a mid-range server.

8
0 667
Question Alex Kogan · May 12, 2017

Hello All,

I have a question / issue regarding the calling list.FindOref(<object from indexOpen call>)
Here is a simple way to reproduce the issue: 
2 classes: Utility.contacttypes and Utility.person
*************************

Class Utility.contacttypes Extends %Persistent
{
Property description As %Library.String(TRUNCATE = 1);
/// Index for property description
Index descriptionIndex On description [ Unique ];
}

*************************

Class Utility.person Extends %Persistent
{
Property types As list Of Utility.contacttypes;
/// Date Setup to recreate an error
ClassMethod DataSetup()
{
    Set ref=##class(Utility.contacttypes).%New()
    Set ref.description="Shipping"
    Do ref.%Save()
    Set ref=##class(Utility.contacttypes).%New()
    Set ref.description="Billing"
    Do ref.%Save()    
    Set tPerson = ##class(Utility.person).%New()
    Do tPerson.types.Clear()
    Set aryContacts(1)=""
    Set aryContacts(2)=""
    Set id=""
    For  
    {  Set id=$o(aryContacts(id))
       Quit:id=""
       Do tPerson.types.InsertObjectId(id)
    }
    Do tPerson.%Save()
    Write !,"Created a record"
    Quit 1
}
/// Reproducing the issue - calling list.FindOref(<object from indexOpen call>) first time returns null!!!
ClassMethod Problem()
{
    Set tPerson = ##class(Utility.person).%OpenId(1)
    For i=1:1:2 {
        If (tPerson.types.FindOref(##class(Utility.contacttypes).descriptionIndexOpen("Billing"))) {
            Write !,"Run Number:"_i_" - Found it ok"
        } else {
            Write !,"Run Number:"_i_" - ERROR!, I did not find it!"
        }
        }
        Close tPerson
        Quit 1
}
}
5
0 430
Question Scott Roth · Nov 30, 2018

I am trying to explore some new possibilities outside of the normal day to day HL7 interfacing we do. I have only done 1 other Web Service interface but it was using a SOAP proxy wizard. Now I am tasked with trying to make a call to an external API 

https://npiregistry.cms.hhs.gov/api/

but I am a bit confused about how to go about doing it. Since they don't have a wsdl, this means it is a REST web service correct? or is it considered an API call?

12
2 1215
Question MARK PONGONIS · Jul 17, 2018

Would like to know if there is an alternative or better way to paginate through a dataset using dynamic SQL than what I am using below. The problem is that as the potential pool of data gets larger, this code slows down to the point of not being useable. In analyzing each line of code below, it appears the slow down is related to the initial rset.%Next() iteration. Is there anything available which does not require a subquery/%VID such as a simple LIMIT/OFFSET?

My code is similar to :

s sql=##class(%SQL.Statement).

31
4 3805
Question Stefan Cronje · Oct 20, 2018

Hi,

We have a few projects and some of these projects share code "libraries". Some of which are persistent classes that are used by multiple systems. All these are currently deployed on Ensemble. We want to move some of the smaller ones to the cloud and make use of IRIS.

The challenge is that once we synchronise the code to IRIS from Atelier, then IRIS changes the storage definitions, which then creates changes to the files. We do not want to commit all these changes to git as it will happen again once someone synchronises with Ensemble.

2
0 425
Question Francis Galiegue · Apr 27, 2016

Hello,

I am still a beginner with COS and am struggling with these concepts. While digging through the official documentation will eventually tell you everything you need to know, getting started is nevertheless not an easy feat...

Is it possible to create a "lists/array/multidimensional 101" page for beginners?

12
0 674
Question Chip Gore · Apr 5, 2016

Hi -

I'm trying to create a method that will automatically create something I can save and use later, which will let me automate data migration from one version of a class to the next.

When I compile a normal persistent class, a "storage" gets created, and I would like to be able to archive some code that would let me recreate this "old storage" so I could access an "older version" from a global and map the values into the current mapping of the class.

2
0 887
Question Rustam Ibragimov · Aug 30, 2016

I know that Cache files can be stored as XML and UDL based files. Is there any way to determine in which format the file(class, routine, dfi and so on) is stored? Because you can easily name your XML based file as class.cls and it will be perfectly valid. 

I know that one way to check whether this file is in XML format is just try to parse it like 

Set st = ##class(%XML.TextReader).ParseStream(contentStream)

if $$$ISERR(st) return $$$NO

else return $$$YES

However, is there a better way? 

4
0 435
Question John Murray · Feb 13, 2018

Documentation here lists the kinds of members a class definition may contain. In summary:

  • Parameters
  • Methods
  • Properties
  • Class queries
  • XData blocks
  • Projections
  • (and some that are relevant only for persistent classes):
    • Storage definitions
    • Indices
    • Foreign keys
    • SQL triggers

Later in the same document, a section headed "Class Member Names" contains this warning:

So I'm interested to hear how other DC members handle this.

  1. Do you comply (or at least attempt to comply) with this?
  2. If so, do you use any tools or naming conventions to assist you?
7
0 488
Question Ravi Nagpal · Oct 10, 2018

Hi, 

Can we create a new class in the studio using any command rather then using the Menu Item Option from Menu Bar in Studio . 

Requirement : Create/Draft a new class and able to extends the other classes using  a command in Cache Class .

In other words , I want to Dig in the Menu Item class from which Menu bar is created in studio and option are provided  Like New..., Open..., etc 

Thanks, 

Ravi 

1
0 314
Question Wendy Griffiths · Jul 22, 2016

I want to override the Get and Set methods of a class property.  The class maps to a pre-existing global. The property is defined like so:

Property Invalid As %Library.Boolean;

with the property mapping to a node like ^GLOBAL(Code,"INVALID")=1
Code is a property in the same class.

The value can be 0 or 1 or the node might not exist. When it doesn't exist I want the value of the SQL field to come out as 0 (false).

12
0 1931
Question John Murray · Oct 2, 2018

Using our cool new debugging extension for Visual Studio Code I'm trying to debug a CreateProjection method of a class, but when I compile it the work apparently gets done in one of the worker jobs, so my breakpoint never triggers.

Is there a compiler flag or qualifier to force the compilation to be done in-process rather than getting handed off to a worker job?

4
0 571
Question Tirthankar Bachhar · Oct 20, 2016

Hi,

When we write unit test cases for cache object script code using %UnitTest.TestCase, what  is the best way to write code to identify code coverage?

So, let say my unit test case hit all 10 lines of code of a method for a given class. So, unit test coverage should be 100% for that. But, using line-by-line coverage [(%Monitor.System.LineByLine] getting wrong percentage, because it also includes code comment/documentation as part of code. So, practically we can not ever achieve 100% of code coverage by using this API.

I'm not sure, if am able to describe the problem properly here.

2
0 959
Question Rustam Ibragimov · Jul 26, 2016

Hello, guys.

I have a set of file names (e.g. file.cls, file2.mac and so on) and I need to check whether these files are mapped in %ALL or current namespace.

I found that if I open Globals in the current namespace I can see mapped packages. And If I open this global I see all files that are  to this namespace and %SYS. The problem is these files are enumerated in a json object(apparently)

ex. "{""class"":{""%Activate.Enum"":{},""%Activate.GenericObject"":{""CreateObject"":0,""GetObject"":0},""%Activate.HandleEvents"")

But, is there a way to determine whether this file is mapped using some method?

1
0 439
Question Rustam Ibragimov · Jul 15, 2016

Hello, guys.

I have an external file that contains data in UDL format(as in Studio, not XML) and I need to somehow overwrite my source file with that file. 

I tried to use this snippet for .mac file

 set rtn = ##class(%RoutineMgr).%OpenId("les.mac")
 rtn.Code.WriteLine("some text")

It says that status is 1, but I don't see any difference in my source file.

Is there any way to overwrite source files, not only .mac but .cls, .int, .dfi?

4
0 681
Question Scott Roth · Dec 21, 2018

Has anyone called any outside Javascript code from inside their class files? I asked a long time ago if there was a way to manipulate an image within Cache Object Script, and since Cache doesn't have any image libraries its not really possible. However I have found Javascript to resize an image and wonder how hard it would be to mesh the two together.

Can anyone share any examples?

Thanks

Scott

9
1 1729
Question Laura Cavanaugh · Nov 4, 2016

Here's an easy one for you; before I spend another hour looking for the answer, how do you convert %ArrayOfDataTypes to an array (that could, say, fit into the %session.Data array, or maybe just some array named info()), and of course back again?

NS>s aodt=##class(%ArrayOfDataTypes).%New()
 
NS>w aodt.SetAt("lcavanaugh","username")
1
NS>w aodt.SetAt("organization","coolcompany")
1
NS>w ##class(%ArrayOfDataTypes).BuildValueArray(aodt,.array)
 
<LIST>zBuildValueArray+1^%Library.ArrayOfDataTypes.1

aodt must be serialzed.  What?

NS>zw array

NS>

3
0 1206