orbitjs / orbit

Composable data framework for ambitious web applications.
https://orbitjs.com
MIT License
2.33k stars 134 forks source link

Determining if a relationship has been loaded. #929

Open SomewhatCloudy opened 2 years ago

SomewhatCloudy commented 2 years ago

At the moment there doesn't seem to be a way of determining if a relationship on a model has already been loaded. For example there is no way to tell if this:

memory.cache.query(q => q.findRelatedRecords(ident, relationKey));

Will always return an array, regardless of if the relation has been loaded already. The same applies to hasOne/belongsTo. This forces you to re-fetch relations that are empty as you don't know if they have already been fetched.

If there a way of finding out if a relation is already loaded, or possibly (and I know this may be breaking) make findRelatedRecords/findRelatedRecord return undefined if there is no relation?

dgeb commented 2 years ago

There are a few alternative ways to check the contents of the cache, but also a caveat.

First, the alternatives:

// Cache#query followed by inspection of the record
const planet = memory.cache.query(q => q.findRecord(ident));
const moonIds = planet?.relationships?.moons?.data;
// Cache#getRecord followed by inspection of the record
const planet = memory.cache.getRecord(ident);
const moonIds = planet?.relationships?.moons?.data;
// Cache#getRelatedRecordsSync - returns `RecordIdentity[] | undefined`
const moonIds = memory.cache.getRelatedRecordsSync(ident, 'moons');

The caveat is that caches by default maintain inverse relationships automatically when they are declared in a schema. Thus, fetching moons but not a planet may still assign those inverse relationships to a sparsely populated planet record in the cache. If you have no inverses on the relationship in question, then this is not a factor.

SomewhatCloudy commented 2 years ago

Thanks I'll give that a try.