Aurelius additional "common" CRUD Endpoint

Hello,

Preamble
I've searched around in support and found that Aurelius is not handling (so far) default values.
I mean, if the (mysql) database structure is this:

CREATE TABLE `com_plants` (
  :
  `isActive` tinyint(1) DEFAULT 1 ,
  :
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Plants';

the auto-generated entity is

[Entity]
[Table('com_plants')]
TctsCOM_plant = class
  private
:
  [Column('isActive', [])]
    FisActive: Nullable<Integer>;
:
public
    constructor Create;
:
    property isActive: Nullable<Integer> read FisActive write FisActive;
:  
end;

My solution at present for default values is to set them in costructor

constructor TctsCOM_plant.Create;
begin
  // set default values (Aurelius missing...)
  FisActive := 1;
end;

Now the real topic question
Since I'm having an admin portal where user can browse records with grids and create new lines (new records) I need to start with default values pre-setup in editing forms whenever a new record is created and before it is posted.
I'm using Aurelius CRUD Endpoints and have set the XDataServer.RoutingPrecedence to Service in order to use XData services with same path (a kind of "aside" path).
So far I've written a service with path "/new" in order to get the default values

[HttpGet]
[Route('/new')]
function getNewRecord: TctsCOM_plant;

// implementation
function TctsComPlantsService.getNewRecord: TctsCOM_plant;
var
  NewPlant: TctsCOM_plant;
begin
  NewPlant := TctsCOM_plant.Create;
  Result := NewPlant;
end;

and pass them to the edit form.
Now, since I have LOTS of entities... is there an (easy) way to add a common path to Aurelius CRUD endpoints and avoiding writing lots of services with a single additional endpoint?

Quite a long post... I hope that all above is clear - thanks in advance!

That's a different thing. The default values are generated server-side. Settings the values at "class-side" is valid, but it's not related at all with the database default values. They can be different.

If you want to receive the default values from database, you should call Manager.Refresh(MyEntity) after the entity is saved.

One thing you can do is simply add a new path parameter to your getNewRecord endpoint, which receives the entity "name". Then in your implementation, you get that information sent by the client and create an instance of the correct class. Of course, then the return value of the service should be a TJSONObject/TJObject (then you serialize the response) or simply a TObject.

Or, you can create a generic version and then declare one specialized version of such generic one for each entity you have.

1 Like

Yes, setting default values class-side is not the same as server-side: apart from the time needed to writing additional code, that could even lead to bugs in case of typing errors or if database default values are "externally" modified...

My idea was NOT to save a new record and fetch it back with Manager.Refresh before the user decided to really save the new record and not hitting the Cancel button on the GUI.

Anyway, changing approach (and avoiding so the setting of defaults at class-side) could be even better.
I guess something like:

Manager.Save(MyEntity);     // new record with default values set server-side
Manager.Refresh(MyEntity);  // get it back and pass it to form

{ user edits and finally closes the form either with Save or Cancel actions }

if actSave then Manager.Save(MyEntity) else Manager.Remove(MyEntity); 

Is it better to enclose it in a Transaction.Commit block and doing a Transaction.Rollback in case of actCancel ? ...or a waste of resources?

Last but not least, your suggestion with getNewRecord plus path is brilliant - I can think of a common service that gives back the "named" new record... :blush:

In my humble opinion, this looks worse.

My point is that database defaults are different from class defaults and even different from defaults set in the UI. Why they have to be the same, and why do you need to define one based on the other.

This is exactly one example of what might happen.

Database defaults are a guarantee for you that your data is consistent according to your business rules. If no data is provided, you save the defaults (if it's the case that this is better than simply raise an error if no value is specified, i.e., values are null).

UI defaults are useful to be a helper for your users. So they don't have to type values you prefill them for they. But you don't need to have a relation between what's in database and what's in your default UIs.

Your point is absolutely interesting and right: DB defaults grant consistency to business rules; UI defaults are helpers to user input and they don't need to be the same.
I will arrange my UIs to have UI defaults as just "hints", that way user inputs will be more "effective".
Thank you very much!

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.