quick icon indicating copy to clipboard operation
quick copied to clipboard

Setting HasMany() Relationship After Relationship Loaded Fails to Update Relationship

Open homestar9 opened this issue 1 year ago • 1 comments

If you update an entity's hasMany relationship after the relationship has been loaded and then attempt to retrieve the relationship, it will not reflect the changes unless you refresh() the entity first.

This is problematic in situations where you need to validate the data you assigned to the entity either via fill, populateModel, saveMany, or set methods. The only workaround is to reload the entity from the database first, which could introduce performance problems when dealing with many operations. It also creates inconsistent behavior where some relationships will reflect the changes and others will not after setting the data.

I suspect the issue has to do with the _relationshipsLoaded property being set to true after you initially retrieve the data and Quick not updating _relationshipsData when the setter is called (or however the data was set).

The solution IMO would be to automatically force set _relationshipsData any time the relationship data is updated via setter, fill, saveMany(), etc. This would prevent unneeded trips to the database and make relationship setting/getting more consistent across relationship types.

Code sample of the problem:

// create or get an entity (creating is easier for sake of example)
prc.task = getInstance( "Task" ).create(); 

// Load the relationship (note: you can also just eager load the relationships above)
prc.task.getTaskLocations();

// sample
prc.locations = [
    getInstance( "TaskLocation" ).create(), 
    getInstance( "TaskLocation" ).create()
];

// Now set the relationship. You have a couple options here:

// 1. Setter method (default for sake of example)
prc.task.setTaskLocations( prc.locations );

// 2. Fill method
//prc.task.fill( { taskLocations: prc.locations } );

// 3. Save Many
//prc.task.taskLocations().saveMany( prc.locations ); 

// now try to access the updated relationsihp.  It will be empty.
// you won't be able to validate against it, or do anything with the relationship data.
writeDump( var=prc.task.getTaskLocations(), top=2 ); // dump the relationship data.

prc.task.refresh(); // refresh the relationship. Danger: This will erase any other data you set but did not save() yet!

// Now the relationship data is loaded because a fresh copy was created from the database.
writeDump( var=prc.task.getTaskLocations(), top=2 ); // dump the relationship data.

homestar9 avatar Sep 02 '22 18:09 homestar9