Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REST-ifying existing model layers (ie. %ZEN.DataModel.ObjectDataModel) #21

Open
copperschnack opened this issue Jan 9, 2023 · 5 comments

Comments

@copperschnack
Copy link

copperschnack commented Jan 9, 2023

In our application, we stripped out a model layer for accessing our %Persistent classes. The model classes inherit from %ZEN.DataModel.ObjectDataModel. They include business logic as triggers on loading or data manipulation, as well as in dedicated methods. We would like to reuse our model layer in a RESTful API. This would enable an evolutionary migration to alternative web frontend frameworks, while the current UI stays fully functional.

CRUD operations could work as follows, distinguishing (R)eading one (R-1) and querying many (R-n) entities. The latter should be realized via %Persistent classes, bypassing the model's initialization logic invoked when loading a dedicated entity for viewing and/or editing.

%ZEN.DataModel.ObjectDataModel

  • R-1: HTTP GET, (single ID) via %OnLoadModel
  • C, U: HTTP POST/PUT, via %OnStoreModel
  • D: HTTP DELETE, via %OnDeleteSource

%Persistent

  • R-n: HTTP GET, query "%pkg.isc.rest.model.adaptor flavour"

With isc-rest being a brilliant approach for REST-ifying existing %Persistent classes, extending its functionality for architectures with model layers could be beneficial for many applications.

@isc-tleavitt
Copy link
Collaborator

isc-tleavitt commented Jan 9, 2023

@copperschnack one immediate challenge here: are the field names used when querying in the R-n case in model terms or %Persistent?

@copperschnack
Copy link
Author

copperschnack commented Jan 9, 2023

@isc-tleavitt IMHO "model terms". They should be determined in the model by a class query which sets the required column aliases.

EDIT: The class query parameters would determine the filtering options available.

@isc-tleavitt
Copy link
Collaborator

isc-tleavitt commented Jan 9, 2023

@copperschnack just to throw another option out there, could use a property parameter - e.g., SQLALIASOF.

Motivating example:

Class DC.Demo.BackingPersistentClass Extends %Persistent
{

Property Foo As %String;

}

Class DC.Demo.SampleModelClass Extends %pkg.isc.rest.model.zenAdaptor
{

Parameter SOURCECLASS = "DC.Demo.BackingPersistentClass";

Property ModelVersionOfFoo As %String(SQLALIASOF = "Foo");

/// This callback method does the actual work of loading values from the source object.
Method %OnLoadModel(pSource As %RegisteredObject) As %Status
{
	Set ..ModelVersionOfFoo = pSource.Foo
	Quit $$$OK
}

/// The rest of the Zen MVC-enabling stuff from %ZEN.DataModel.ObjectDataModel goes here; the above is just a snippet.

}

How does that approach sound?

@copperschnack
Copy link
Author

@isc-tleavitt SQLALIASOF sounds like a perfect fit for standard models. We might be even more flexible with an SqlComputeCode equivalent property parameter which could be brought into the SQL statement on query generation. This would allow access even to calculated model properties, if required.

What do you think about that?

@isc-tleavitt
Copy link
Collaborator

We'd allow SQLALIASOF to be an expression - I think that should generally work. To be clear, the main purpose of this is filtering query results. The model representation will be based on loading the model from the source object by ID, where the query returns the IDs in question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants