Bookshelf.JS: 相关模型在被要求之前正在尝试使用
Bookshelf.JS: Related Model is trying to be used before being required
我有两个相关的模型,Customers 和 Addresses。当我尝试创建具有相关地址的客户时,我首先发现了这个问题。出于我们的目的,单个客户可以有多个地址,并且在创建新客户时,我们希望在创建客户的同时创建一个地址。
我仔细研究了文档并尽可能地建立了关系,这似乎工作得很好,但后来我注意到当我将两个模型一起包含在模块中时,(即我的 routes/controllers), 我得到了循环引用。
长话短说,我的研究让我将 registry
插件添加到我的 bookshelf.js
文件中。这在当时有效,但现在看来我的 Address
模型在客户中引用时未正确导出。
这是我当前配置的一个片段
// bookshelf.js
const bookshelf = require('bookshelf')(knex);
bookshelf.plugin([
'registry',
]);
module.exports = bookshelf;
// customers.js
const bookshelf = require('../bookshelf');
const Address = require('./address');
const Customer = bookshelf.Model.extend({
tableName: 'customers',
addresses: function () {
return this.hasMany('Address');
},
}, {
customCreate: function (attributes) {
return this.forge(attributes)
.save()
.tap(c => {
return Address.forge(attributes)
.save({
customer_id: c.get('id'),
});
})
}
});
module.exports = bookshelf.model('Customer', Customer);
// address.js
const bookshelf = require('../bookshelf');
const Customer = require('./customer');
const Address = bookshelf.Model.extend({
tableName: 'addresses',
customer: function () {
return this.belongsTo('Customer');
}
});
module.exports = bookshelf.model('Address', Address);
我开始注意到,当我 运行 Customer.customCreate()
时,我收到一条错误消息 Address.forge is not a function
。我将一些控制台日志放入我的 customer.js
文件中,发现 Address
在 customer.js
中被引用时是一个空对象 ({}
)。但是,在其他地方,它会返回正确的 Bookshelf 模型。
在我看来,我正试图在客户正确要求之前使用我的 Address 模型,这让我想知道我是否正确地构建了我的项目和模型,或者我是否需要进行任何更改。
有一个循环引用问题好吧。构建模型以避免此类问题的最佳方法是在应用程序初始化期间将它们全部加载到一个文件中,例如index.js
在您的模型目录中,将每个模型附加到一个对象并导出该对象。然后您只需 require()
该文件并在一个地方访问所有模型。
但是,要以更简单的方式解决您的问题,您只需对 customCreate()
方法进行一次更改:
customCreate: function (attributes) {
return this.forge(attributes)
.save()
.tap(c => this.related('addresses').create(attributes))
}
}
这利用 Collection.create
方法轻松地在集合中创建新模型,并且由于它用于关系,因此还将设置正确的外键。
请注意,Registry 插件不会将您从循环依赖问题中解救出来,但它可以让您以避免它们的方式编写您的模型。
我有两个相关的模型,Customers 和 Addresses。当我尝试创建具有相关地址的客户时,我首先发现了这个问题。出于我们的目的,单个客户可以有多个地址,并且在创建新客户时,我们希望在创建客户的同时创建一个地址。
我仔细研究了文档并尽可能地建立了关系,这似乎工作得很好,但后来我注意到当我将两个模型一起包含在模块中时,(即我的 routes/controllers), 我得到了循环引用。
长话短说,我的研究让我将 registry
插件添加到我的 bookshelf.js
文件中。这在当时有效,但现在看来我的 Address
模型在客户中引用时未正确导出。
这是我当前配置的一个片段
// bookshelf.js
const bookshelf = require('bookshelf')(knex);
bookshelf.plugin([
'registry',
]);
module.exports = bookshelf;
// customers.js
const bookshelf = require('../bookshelf');
const Address = require('./address');
const Customer = bookshelf.Model.extend({
tableName: 'customers',
addresses: function () {
return this.hasMany('Address');
},
}, {
customCreate: function (attributes) {
return this.forge(attributes)
.save()
.tap(c => {
return Address.forge(attributes)
.save({
customer_id: c.get('id'),
});
})
}
});
module.exports = bookshelf.model('Customer', Customer);
// address.js
const bookshelf = require('../bookshelf');
const Customer = require('./customer');
const Address = bookshelf.Model.extend({
tableName: 'addresses',
customer: function () {
return this.belongsTo('Customer');
}
});
module.exports = bookshelf.model('Address', Address);
我开始注意到,当我 运行 Customer.customCreate()
时,我收到一条错误消息 Address.forge is not a function
。我将一些控制台日志放入我的 customer.js
文件中,发现 Address
在 customer.js
中被引用时是一个空对象 ({}
)。但是,在其他地方,它会返回正确的 Bookshelf 模型。
在我看来,我正试图在客户正确要求之前使用我的 Address 模型,这让我想知道我是否正确地构建了我的项目和模型,或者我是否需要进行任何更改。
有一个循环引用问题好吧。构建模型以避免此类问题的最佳方法是在应用程序初始化期间将它们全部加载到一个文件中,例如index.js
在您的模型目录中,将每个模型附加到一个对象并导出该对象。然后您只需 require()
该文件并在一个地方访问所有模型。
但是,要以更简单的方式解决您的问题,您只需对 customCreate()
方法进行一次更改:
customCreate: function (attributes) {
return this.forge(attributes)
.save()
.tap(c => this.related('addresses').create(attributes))
}
}
这利用 Collection.create
方法轻松地在集合中创建新模型,并且由于它用于关系,因此还将设置正确的外键。
请注意,Registry 插件不会将您从循环依赖问题中解救出来,但它可以让您以避免它们的方式编写您的模型。