2014-11-22 75 views
1

假設我們有一個連接表vehicle_inspections和另一個連接表inspection_actions,以及actions,vehicles, and檢查的基本表。BookshelfJs未能創建嵌套關係

可以說,我的願望以下DB條目:

vehicles 
---------------------------- 
id  make 
---------------------------- 
1   Toyota 



actions 
------------------------------- 
id  description 
------------------------------- 
2   Check Tire Pressue 

inspections 
------------------------------- 
id  location  date 
------------------------------- 
3   New York  tomorrow 

vehicle_inspections 
-------------------------------- 
vehicle_id  inspection_id 
-------------------------------- 
1    3 

inspection_actions 
-------------------------------- 
inspection_id  action_id 
-------------------------------- 
3     2 

及以下書架類

inspection_actions.js

(function() { 
    'use strict'; 
    var Repository = require('../repository'); 
    module.exports = Repository.Model.extend({ 
     tableName: 'inspection_actions', 
    }); 
})(); 

vehicle_inspections.js

(function() { 
    'use strict'; 
    var Repository = require('../repository'); 

    module.exports = Repository.Model.extend({ 
     tableName = 'vehicle_inspections', 
     inspection: function() { 
     return this.belongsTo(require('inspection')); 
     }, 
     fetchOrCreate: function(vehicleId, inspectionId, options) { 
     var self = this; 
     return self.query(function (qb) { 
      qb.where({ 
      vehicle_id: vehicleId, 
      inspection_id: inspectionId 
      }); 
     )}.fetch(options || {}).then(function (model) { 
      if (!model) { 
      model.save({ 
       vehicle_id: vehicleId, 
       inspection_id: inspectionId 
      }); 
      return model; 
     }; 
     } 
    }; 
}); 

個inspection.js

... 
module.exports = Repository.Model.extend(_.extend({ 
    tableName: 'inspections', 
    actions: function() { 
    return this.hasMany(require('./inspection-action')); 
    } 
})); 

和路徑:

new VehicleInspection().fetchOrCreate(req.params.vehicle_id, req.params.inspection_id, {withRelated: ['inspection.actions']}) 
.then(function (vehicleInspection) { 
    var inspection = vehicleInspection.related('inspection'); 
    console.log(inspection); 
    console.log(inspection.related(actions); 
    }) 

檢查控制檯日誌打印出正確的檢查,但是,他毫無來由是什麼在數據庫中的第二個的console.log打印出一個空結果

{ length: 0, 
    models: [], 
_byId: {}, 
    ... 
    targetIdAttribute: 'id', 
foreignKey: undefined, 
parentId: undefined, 
parentTableName: 'tasks', 
parentIdAttribute: 'id', 
parentFk: undefined } } 

此「不良」行爲僅在首次創建projectTasks條目時發生。看起來正在發生的情況是,inspection_action表沒有通過嵌套的withRelated填充。我怎麼能得到這個工作嵌套創建工作?

回答

4

我不完全清楚你想達到什麼,但這裏是我通常會設置的東西。首先我想創建一個基礎模型(假設其保存爲base.js),我想你會遇到一些問題,與循環依賴,因此,使用書架註冊表插件將是一件好事:

var config = { 
    client: // whatever client you are using, 
    connection: // url to your database 
}; 
var db = require('knex')(config); 
var Bookshelf = require('bookshelf')(db); 
var Base = Bookshelf.Model.extend({ 
    // Put anything here that will be helpful for your use case 
}); 
Bookshelf.plugin('registry'); 

Base.model = Bookshelf.model.bind(Bookshelf); 
module.exports = Base; 

下一頁創建您的車輛型號:

require('inspection'); 
require('action'); 
var Base = require('base'); 

var Vehicle = Base.Model.extend({ 
    tableName = 'vehicles', 
    inspections: function() { 
    return this.belongsToMany('Inspection', 
     'inspections_vehicles', 'vehicle_id', 'inspection_id'); 
    }, 
    actions: function() { 
    return this.belongsToMany('Action', 
     'actions_vehicles', 'vehicle_id', 'action_id'); 

    } 
}; 
module.exports = Base.model('Vehicle', Vehicle); 

然後檢查模型:

require('vehicle'); 
var Base = require('base'); 

var Inspection = Base.Model.extend({ 
    tableName = 'inspection', 
    vehicles: function() { 
    return this.belongsToMany('Vehicle', 
     'inspections_vehicles', 'inspection_id', 'vehicle_id'); 
    } 
}; 
module.exports = Base.model('Inspection', Inspection); 

最後一個動作模式:

var Base = require('base'); 

var Action = Base.Model.extend({ 
    tableName = 'actions', 
}; 
module.exports = Base.model('Action', Action); 

現在假定數據庫尚未與您所提供的數據填充,我們就可以填充它:

var Inspection = require('inspection'); 
var Vehicle = require('vehicle'); 
var Action = require('action'); 
var toyota; 
var newYorkInspection 

Vehicle.forge().save({name: 'Toyota'}) 
    .then(function(vehicle) { 
    toyota = vehicle; 
    return Inspection.forge().save({location: 'New York', date: 'Tomorrow'});  
    }).then(function(inspection){ 
    newYorkInspection = inspection; 
    return toyota.inspections().attach(newYorkInspection); 
    }).then(function() { 
    return Action.forge().save({description: 'Check Tire Pressure'}); 
    }).then(function(tirePressureAction) { 
    return toyota.actions().attach(tirePressureAction); 
    }); 

現在我可以與相關的行動和檢查獲取豐田汽車:

var Vehicle = require('vehicle'); 
return Vehicle.forge({'name': 'Toyota'}).fetch({ 
    withRelated: ['inspections', 'actions'] 
}).then(function(toyota){ 
    var toyotaInspections = toyota.related('inspections'); 
    var toyotaActions = toyota.related('actions'); 
}); 
+0

謝謝你提供的信息豐富的答案(我已經upvoted)。 經過一些更深入的挖掘,我已經將問題縮小到了創建上,並適當地修改了我的問題以充分暴露fetchOrCreate並進行詳細說明。 簡短版本是:.fetch按原樣運行,.save如何不創建嵌套關係'inspection.actions',而不是使用正確的條目填充inspection_actions表並因此正確返回空數組。我很樂意聽到你有任何關於解決這個問題的想法:) – 2014-11-23 07:17:17

+0

首先,嘗試vehicleInspection.related('actions')來獲取行動。其次,當您調用fetchOrCreate時,如果由於對象不存在而導致獲取失敗,並且創建它,則返回的模型將僅爲inspection_action模型,並且沒有關係。如果你想要關係,你必須在保存之後再做一次提取。 – 2014-11-24 17:04:59

+0

謝謝:)你是一個學者,一個文雅的女人 – 2014-11-24 18:17:58