I am quite new to loopback, so it maybe that I am missing the point, however I have defined a couple of models; MenuCategory and Image, and these have a many to many relationship. So I have defined a hasManyThrough relationship using the following configs:
MenuCategory model
{
"name": "MenuCategory",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"mixins": {
"I18n": {
"i18nModel": "MenuCategoryI18N"
}
},
"properties": {
"type": {
"type": "string",
"required": true
},
"parentId": {
"type": "number",
"required": true
},
"order": {
"type": "number"
}
},
"validations": [],
"relations": {
"translations": {
"type": "hasMany",
"model": "MenuCategoryI18N",
"foreignKey": "category_id"
},
"images": {
"type": "hasMany",
"model": "Image",
"foreignKey": "category_id",
"through": "CategoriesToImages"
}
},
"acls": [],
"methods": {}
}
Image model
{
"name": "Image",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"file_name": {
"type": "string"
},
"url": {
"type": "string",
"required": true
},
"folder_id": {
"type": "number",
"required": true
}
},
"validations": [],
"relations": {
"categories": {
"type": "hasMany",
"model": "MenuCategory",
"foreignKey": "image_id",
"through": "CategoriesToImages"
}
},
"acls": [],
"methods": {}
}
CategoriesToImages link-model:
{
"name": "CategoriesToImages",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"category_id": {
"type": "number",
"required": true
},
"image_id": {
"type": "number",
"required": true
}
},
"validations": [],
"relations": {
"menucategories": {
"type": "belongsTo",
"model": "MenuCagegories",
"foreignKey": "category_id"
},
"image": {
"type": "belongsTo",
"model": "Image",
"foreignKey": "image_id"
}
},
"acls": [],
"methods": {}
}
I was under the impression that I should be able to remove a category and it rip down the entries in the link table 'categories-to-images' automatically, but this doesn't appear to be happening. I also don't appear to be able to link an image to a category using:
MenuCategory.images.add(Image);
..as the docs suggest, I just get an error.
Any help would be most grateful!
"relations": {
"menucategories": {
"type": "belongsTo",
"model": "MenuCagegories", // spelled wrong
"foreignKey": "category_id"
},
"image": {
"type": "belongsTo",
"model": "Image",
"foreignKey": "image_id"
}
},
Try fixing the typo first and see what happens.
In the future (not everyone does this but they should), to get help as fast as possible, fork a loopback-sandbox and recreate the issue and put the _steps to reproduce_ in the README.md. That way I can see exactly what your setup looks like including your configs. Hope that helps!
Hi, sorry I have been on holiday.
Thanks for the typo spot, unfortunately it didn't make a difference. I have had to write a cascade mixin. I will try and create a sandbox for the issue.
@tomcooksey,if you do manage to get a sandbox up, please post the link in here and mention me in the comment.
:+1: I can confirm this, deleting an object of a model that has a hasManyThrough relation to another model does not delete the entries in the link (through) table.
I never managed to get a sandbox setup, but it doesn't seem like it's a difficult bug to replicate. If anyone's interested, I wrote this cascade mixin to achieve this functionality. I supply it on the basis that it worked for me and people are free to use it if it helps them:
var _ = require('lodash'),
loopback = require('loopback');
/**
* Mixin that does a cascade delete on related items that are identifed in the
* settings for this mixin within a particular model
* @param Model
* @param options
*/
module.exports = function(Model, options) {
Model.observe('after delete', function(ctx, next) {
//Get the ID of the record that's being deleted
var promises = [],
requestContext = loopback.getCurrentContext(),
id = requestContext.active.http.req.params.id,
keys = Object.keys(options);
_.each(keys, function(model) {
var foreignKey = options[model],
linkModel = loopback.getModelByType(model),
where = {};
where[foreignKey] = id;
promises.push(linkModel.destroyAll(where));
});
Promise.all(promises)
.then(function() {
next();
});
});
};
Configured in model thusly:
"mixins": {
"Cascade": {
"linkedModelName": "foreignKey"
},
}
:+1: thanks, the mixin seems to work fine for me too, except that I had to change
id = requestContext.active.http.req.params.id,
to
id = ctx.where.id,
Ah yes, that was me playing with something. Glad it works!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.
Most helpful comment
I never managed to get a sandbox setup, but it doesn't seem like it's a difficult bug to replicate. If anyone's interested, I wrote this cascade mixin to achieve this functionality. I supply it on the basis that it worked for me and people are free to use it if it helps them:
Configured in model thusly: