Ember.js EmberData:两个与多个关系相关的模型
我有一个应用程序逻辑,需要两个模型具有许多关系。例如,设想一组GitHub问题可以用几个标签进行标记 我正在尝试使用扩展默认RESTAdapter的适配器。所有应用程序都可以正常工作,但double-hasMany关系引发异常。深入研究代码,一个方法inverseBelongsToForHasMany会抛出一个异常 所以,我猜Ember.Data不支持两个模型之间的关联,因为这两个模型在双方都有很多关系,每个hasMany都需要一个关联的belongsTo。我的问题是:Ember.js EmberData:两个与多个关系相关的模型,ember.js,ember-data,Ember.js,Ember Data,我有一个应用程序逻辑,需要两个模型具有许多关系。例如,设想一组GitHub问题可以用几个标签进行标记 我正在尝试使用扩展默认RESTAdapter的适配器。所有应用程序都可以正常工作,但double-hasMany关系引发异常。深入研究代码,一个方法inverseBelongsToForHasMany会抛出一个异常 所以,我猜Ember.Data不支持两个模型之间的关联,因为这两个模型在双方都有很多关系,每个hasMany都需要一个关联的belongsTo。我的问题是: 这是否得到支持,而问题只
提前感谢余烬数据中尚不支持多对多关系。目前,一种可能的解决方法是手动管理联接表
A = DS.Model.extend({
abs: DS.hasMany('Ab'),
bs: function () {
return this.get('abs').getEach('b');
}
});
Ab = DS.Model.extend({
a: DS.belongsTo('A'),
b: DS.belongsTo('b')
});
B = DS.Model.extend({
abs: DS.hasMany('Ab'),
bs: function () {
return this.get('abs').getEach('a');
}
});
这只是一个起点。然后,您需要自定义模型和适配器,以便以有效的方式发送/接收/保存记录
例如,在我们的应用程序中,我们在hasMany关系中引入了一个{includedJoin:true}
选项,并将连接表声明为JoinModel
A = DS.Model.extend({
abs: DS.hasMany('Ab', {includeJoin: true}),
...
});
DS.JoinModel = DS.Model.extend();
Ab = DS.JoinModel.extend({
... belongsTo relationships ...
});
然后在适配器中,我们重写create/update/delete方法,以便忽略存储中的联接表生命周期
createRecords: function (store, type, records) {
if (!DS.JoinModel.detect(type)) {
this._super(store, type, records);
}
}
最后,在序列化程序中,我们重写了addHasMany
函数,以便将连接数据作为父模型中的嵌入ID发送到服务器
addHasMany: function (hash, record, key, relationship) {
var
options = relationship.options,
children = [];
//we only add join models, use of `includeJoin`
if (options.includedJoin) {
record.get(relationship.key).forEach(function (child) {
children.pushObject(child.toJSON({
includeId: true
}));
});
hash[key] = children;
}
}
服务器端我们将Rails与ActiveModelSerializer一起使用,因此唯一一点棘手的定制是当我们更新父模型时,我们手动管理联接关系,并在联接表中创建/删除条目。我们使用类似的方法创建关联对象。但是,我们没有重写存储区中的方法,而是将连接对象添加到api中
A = DS.Model.extend({
abs: DS.hasMany('Ab'),
bs: function () {
return this.get('abs').getEach('b');
}
});
Ab = DS.Model.extend({
a: DS.belongsTo('A'),
b: DS.belongsTo('b')
});
B = DS.Model.extend({
abs: DS.hasMany('Ab'),
bs: function () {
return this.get('abs').getEach('a');
}
});
因此,在我们创建的模型中:
App.Hashtag = DS.Model.extend({
hashtagUsers: DS.hasMany('App.HashtagUser', {key: 'hashtag_user_ids'})
});
App.User = DS.Model.extend({
hashtagUsers: DS.hasMany('App.HashtagUser', {key: 'hashtag_user_ids'})
});
App.HashtagUser = DS.Model.extend({
user: DS.belongsTo('App.User'),
hashtag: DS.belongsTo('App.Hashtag')
});
然后,对于事务,我们只需更改并提交join对象
App.UserController = Ember.ObjectController.extend({
followHashtag: function(tag) {
var hashtagUser;
hashtagUser = this.get('hashtagUsers').createRecord({
hashtag: tag
});
tag.get('hashtagUsers').pushObject(hashtagUser);
App.store.commit();
}
unfollowHashtag: function(tag) {
var itemToRemove;
itemToRemove = this.get('hashtagUsers').find(function(hashtagUser) {
if (hashtagUser.get('hashtag') === this) {
return true;
}
}, tag);
this.get('hashtagUser').removeObject(itemToRemove);
tag.get('hashtagUser').removeObject(itemToRemove);
itemToRemove.deleteRecord();
App.store.commit();
}))
API创建了一个HashtagUser对象,follow方法只是将该用户添加到两个相关部分中
要删除,它会弹出关联对象并销毁关联对象
虽然它并没有看上去那么优雅,但我们的主要动机是,当余烬数据得到更新时,我们应该能够将其转换为一个简单的股票余烬数据支持版本,这比我们搞乱商店本身要容易得多。感谢您的详细回复。手动处理关系是我们知道的起点,但您对必须在适配器/序列化程序中进行的更改的详细分析令人惊讶。很高兴知道这一点可以帮助您:)。这不是完美的,显然是黑客,但它似乎为我们工作。我希望您能够成功地实现服务器端处理此问题。在最新版本的Ember Data中,您可以使用
App.ApplicationSerializer=DS.ActiveModelSerializer.extend({})
使用带下划线的外键。