2015-06-12 50 views
2

我有一個loopback-js API。如何輕鬆複製Loopback JS中的模型和相關模型

其中我有一個產品模型,它相當複雜,有很多相關的模型。 (元數據,技術要求,標籤,域名,targetAudience,...)

我在寫CMS,我希望用戶能夠輕鬆地複製產品,然後只是改變一些小的東西,因爲所有這些產品的許多數據都是相同的。

有沒有一種簡單的方法在Loopback JS中做到這一點?例如product.saveAs();

我看到它的唯一方法是從產品獲取數據,然後刪除ID並將數據作爲新產品插入到數據庫中,然後對所有相關模型執行相同操作。

回答

2

因爲我在網上找不到簡單的答案,所以我想出了一個可以用模型實現的混合。該混入定義了一個重複的方法,它通過檢查模型定義複製的模式,所以它遍歷關係樹,複製或鏈接相關的項目,以及:

共同

混入文件/混入/ 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" 
    ] 
}, 

模型定義需要的地方,要使用的mixin:在自己的風險

... 
"acls": [ 
    { 
     "accessType": "*", 
     "principalType": "ROLE", 
     "principalId": "$everyone", 
     "permission": "DENY" 
    } 
], 
"methods": [], 
"mixins": { 
    "Duplicate": true 
} 

使用

它遠非完美,但現在,它足夠滿足我需要的。也許別人也可以使用它。

目前它複製模型數據本身(包括belongsTo關係的外鍵和嵌入模型),hasMany(遞歸)和hasToAndBelongsToMany(非遞歸)。如果你想擁有ManyThrough功能,​​最好爲'through-table'添加一個額外的hasmany關係,而不是重複。

事情我想補充的未來:如果混入叫上一個有效的環回模式

  • add選項來指定哪些關係應包括
  • 附加

    • 查了,很多通過功能
  • +0

    這將是很酷,如果你可以提交一個公關https://github.com/beeman/loopback-angular-admin,增強它利用這個作爲一個例子樂:) – pulkitsinghal