Question
· Feb 6, 2019

Populating test/initial data

How do you populate and update test/initial data for you classes?

CSV tables? Globals export? And how do you update test data?

Here's one way I found useful for small projects.

Class utils.Test Extends (%Persistent, %XML.Adaptor)
{

Parameter XDATA = "Data";

Property PropertyA As %String;

/// set sc = ##class(utils.Test).Export()
ClassMethod Export() As %Status
{
    quit:$classmethod($classname(), "%Extends", "%XML.Adaptor")=0 $$$ERROR($$$GeneralError, "Class " _ $classname() _ " should extend %XML.Adaptor")
    
    if ##class(%Dictionary.XDataDefinition).IDKEYExists($classname(), ..#XDATA) {
        set xdata = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), ..#XDATA)
    } else {
        set xdata = ##class(%Dictionary.XDataDefinition).%New($classname() _  ":" _ ..#XDATA)
    }
    
    #dim stream As %Stream.TmpCharacter
    set stream = xdata.Data
    
    do stream.Clear()
    do stream.WriteLine("<xml>")
    
    for i=1:1:$g(@##class(utils.Test).GetIdGlobal(), 0) {
        set obj = ..%OpenId(i)
        do obj.XMLExportToStream(.stream)
        do stream.WriteLine("")
    }
    do stream.WriteLine("</xml>")
    quit xdata.%Save()
}

/// do ##class(utils.Test).Import()
ClassMethod Import(killExtent As %Boolean = {$$$YES}) As %Status
{
    #dim sc As %Status = $$$OK
    set xdata = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), ..#XDATA,,.sc)
    quit:$$$ISERR(sc) sc
    
    #dim stream As %Stream.TmpCharacter
    set stream = xdata.Data
    
    set reader = ##class(%XML.Reader).%New()
    set sc = reader.OpenStream(stream)
    quit:$$$ISERR(sc) sc
    do reader.Correlate(..GetXMLName(), $classname())
    
    do:killExtent ..%KillExtent()
    while reader.Next(.obj, .sc) {
        quit:$$$ISERR(sc)
        
        set sc = obj.%Save()
        quit:$$$ISERR(sc)
    }
    
    quit sc
}

/// Get class XMLName
/// w ##class(utils.Test).GetXMLName()
ClassMethod GetXMLName(class As %Dictionary.CacheClassname = {$classname()}) As %String
{
    set xmlname = ..#XMLNAME
    set:xmlname="" xmlname = $$$ClassShortName(class)
    quit xmlname
}

/// Get the name of Id global from active storage.
/// w ##class(utils.Test).GetIdGlobal()
ClassMethod GetIdGlobal(class As %Dictionary.CacheClassname = {$classname()}) As %String
{
    quit:'$$$comClassDefined(class) ""
    set strategy = $$$comClassKeyGet(class, $$$cCLASSstoragestrategy)
    quit $$$defMemberKeyGet(class, $$$cCLASSstorage, strategy, $$$cSDEFidlocation)
}

}

When you want to save class data (i.e. for project release) you call Export method and it creates XData definition that holds serialized objects:

XData Data
{
<xml>
  <Test><PropertyA>1</PropertyA></Test>
  <Test><PropertyA>2</PropertyA></Test>
</xml>
}

And to load data you need to call Import method, which would read XData and save the objects found there.

If you have a lot of classes, you can move all these methods to a separate class, and add it as a superclass to the persistent classes you want to save.

It could also have ExportAll/ImportAll methods iterating over results of %Dictionary.ClassDefinitionQuery:SubclassOf query.

What's your approach?

This approach obviously can't hold a lot of data.

Discussion (3)1
Log in or sign up to continue