thinky
thinky copied to clipboard
What is the best way to manage "relational" defaults?
Question
Say I wanted to have a default for a model (ModelA) that was the id of another model (ModelB). The schemas look like this:
const ModelA = thinky.createModel('ModelA', {
id: type.string().uuid(4),
name: type.string(),
modelBId: type.string().uuid(4),
});
const ModelB = thinky.createModel('ModelB', {
id: type.string().uuid(4),
title: type.string().default('Untitled'),
});
When I create a new modelA, I want it to automatically create a new modelB with some default attributes and add the id of that newly created modelB to the modelBId attribute of modelA. So it would work like this:
ModelA.save({ name: 'Test' })
.then((m) => {
console.log(m.modelBId); // ID of newly created modelB
})
.catch(err => console.log(err));
Is this possible? I know that .default() can accept a function but that function assumes a synchronous process because it has to next support like the pre and post event hooks do.
I guess you can indeed use pre('save') which can be used to set default values if you want:
ModelA.pre('save', function(next) {
this.modelB = this.modelB || new ModelB();
});
That would not work as I need the id of the default-created ModelB. This would assume that I store modelB nested in the document. However it is stored separately and referenced with the id and a hasOne relationship.
You could still do something like that :
Assuming you have express app. You can use lots of things global, some memory store, etc.
const defaultModelB = new ModelB(...)
app.locals.defaultModelB = defaultModelB
ModelA.pre('save', (next) => {
this.modelB = this.modelB || app.locals.defaultModelB;
})
Note: you need either the id if you want to store this.ModelB_id or the object if you ant to go with this.modelB
The id would be undefined. Ids are not created until they are saved in the DB.
const defaultModelB = new ModelB(...);
console.log(defaultModelB.id); // undefined
You can use a middleware like that :
app.use((req, res, next) => {
if (!defaultModelB.isSaved()) {
defaultModelB.save().then(() => next())
}
next()
})
Okay, but that's not what I am looking for. To be specific, I want to handle this all with only the Model. Including Express middlewares is not a solution for me.
I think even in Eloquent there are no default relationships