2015-06-12 2 views
2

У меня есть loopback-js API.Как я могу легко скопировать модели и связанные с ними модели в Loopback JS

В нем у меня есть модель продукта, которая довольно сложная, со многими родственными моделями. (метаданные, технические требования, теги, домены, targetAudience, ...)

Я пишу CMS, и я хочу, чтобы пользователи могли легко копировать продукты, а затем просто изменять некоторые мелочи, потому что многие из этих данных одинаковы для всех этих продуктов.

Есть ли простой способ сделать это в Loopback JS? Например, product.saveAs();

Единственный способ, по которому я вижу, это получить данные от продукта, а затем удалить идентификаторы и вставить данные в качестве нового продукта в базу данных, а затем сделать то же самое для всех связанных моделей ...

ответ

2

Поскольку я не мог найти простой ответ в Интернете, я придумал микс, который можно реализовать с помощью модели. 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 Модели опции
  • надстройки указать, какие отношения должны быть включены
  • С-многие -правленная функциональность
+0

Было бы здорово, если бы вы могли отправить PR в https://github.com/beeman/loopback-angular-admin, что улучшит его, чтобы использовать это как пример le :) – pulkitsinghal

Смежные вопросы