Поскольку я не мог найти простой ответ в Интернете, я придумал микс, который можно реализовать с помощью модели. Mixin определяет дубликат метода, который дублирует модель, проверив определение модели, так это обход отношения дерева, чтобы дублировать или связанную ссылку элементы, а также:
Mixin файл в общем/Примеси/duplicate.js
var async = require ('async');
function Duplicate(Model){
Model.duplicate = function (id, cb) {
var self = this;
var models = Model.app.models;
var includeRelations = Object.keys(self.definition.settings.relations);
self.findById(id, {include: includeRelations}, function(err, fromInstance){
if(err){
return cb(err);
}
var fromData = JSON.parse(JSON.stringify(fromInstance));
delete fromData.id;
self.create(fromData, function(err, newInstance){
if(err){
return cb(err);
}
var relations = self.definition.settings.relations;
var operations = [];
for(var relationName in relations){
var relation = relations[relationName];
switch(relation.type){
case "hasAndBelongsToMany": //add extra links to relation
if(relation.foreignKey == "") relation.foreignKey = "id";
for(var i = 0; i < fromData[relationName].length; i++){
var relatedItem = fromData[relationName][i];
operations.push(async.apply(newInstance[relationName].add, relatedItem[relation.foreignKey]));
}
break;
case "hasMany": //create extra items
if(relation.through){
//don copy many through relations, add an extra has many on the intermediate
} else {
// copy ze shit, and recursively check if child relations have to be duplicated
for(var i = 0; i < fromData[relationName].length; i++) {
var relatedItem = fromData[relationName][i];
operations.push(async.apply(
function(relation, relatedItem, newInstance, cb2){
try {
models[relation.model].duplicate(relatedItem.id, function(err, duplicatedInstance){
if(err){
cb2(err);
}
var fk = relation.foreignKey || self.definition.name.substr(0, 1).toLowerCase() + self.definition.name.substr(1) + "Id";
duplicatedInstance.updateAttribute(fk, newInstance.id , cb2);
});
} catch(err){
cb2(err);
}
},
relation, relatedItem, newInstance));
}
}
break;
default: //do nothing
}
}
if(operations.length > 0){
async.parallel(operations, function (err, results) {
if (err) cb(err);
cb(null, newInstance);
});
} else {
cb(null, newInstance);
}
});
})
}
}
module.exports = Duplicate;
Обновление вашей модели-конфигурации:
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"../common/mixins"
]
},
Определить в модели, где это необходимо, что вы хотите использовать подмешать:
...
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}
],
"methods": [],
"mixins": {
"Duplicate": true
}
Используйте на свой страх и риск
Это далеко не идеальный, но на данный момент он достаточно хорош для того, что мне нужно. Возможно, кто-то еще может это использовать.
В настоящее время это сама копия данных модели (которая включает в себя внешние ключи от отношения к отношениям и встроенные модели), hasMany (рекурсивно) и hasToAndBelongsToMany (не рекурсивно). Если вы хотите использовать функции hasManyThrough, лучше добавьте дополнительное hasmany-отношение к «сквозной таблице», которое будет дублироваться вместо этого.
Вещь, которые я мог бы добавить в будущем:
- чека, если Примесь вызывается действительной Loopback Модели опции
- надстройки указать, какие отношения должны быть включены
- С-многие -правленная функциональность
Было бы здорово, если бы вы могли отправить PR в https://github.com/beeman/loopback-angular-admin, что улучшит его, чтобы использовать это как пример le :) – pulkitsinghal