EmberData:与hasMany关系相关的两个模型

esc*_*nt3 4 ember.js ember-data

我有一个应用程序逻辑,需要两个模型具有互惠的hasMany关系.例如,想象一组可以用多个标签标记的GitHub问题.

我正在尝试使用扩展默认RESTAdapter的适配器.所有应用程序都运行正常,但double hasMany关系会抛出异常.深入研究代码,inverseBelongsToForHasMany方法抛出异常.

所以,我猜Ember.Data不支持两个模型与两侧的hasMany关系的关联,并且每个hasMany都需要关联的belongsTo.我的问题是:

  1. 这是否受到支持,问题是我做错了什么?
  2. 如果不支持,是否计划出现功能?
  3. 在这种应用中,这是一种要避免的关联类型吗?如果是这样,哪种方法或解决方法最好?

提前致谢

sly*_*7_7 8

ember-data尚不支持多对多关系.目前,一种可能的解决方法是手动管理连接表.

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'); 
  }
});
Run Code Online (Sandbox Code Playgroud)

这只是一个起点.然后,您需要自定义模型和适配器,以便以工作方式发送/接收/保留记录

例如,在我们的应用程序中,我们{ includedJoin: true }在hasMany关系中引入一个选项,并将连接表声明为JoinModel

A = DS.Model.extend({
  abs: DS.hasMany('Ab', {includeJoin: true}),
  ...
});

DS.JoinModel = DS.Model.extend();

Ab = DS.JoinModel.extend({
  ... belongsTo relationships ...
});
Run Code Online (Sandbox Code Playgroud)

然后在Adapter中,我们覆盖create/update/delete方法,以便忽略商店中的连接表生命周期

createRecords: function (store, type, records) {
  if (!DS.JoinModel.detect(type)) {
    this._super(store, type, records);
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,在序列化程序中,我们重写该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;
  }
}
Run Code Online (Sandbox Code Playgroud)

服务器端我们正在使用Rails和ActiveModelSerializer,所以唯一一个棘手的定制是当我们更新父模型时,我们手动管理连接关系,并在连接表中创建/删除条目.


And*_*lan 8

我们使用类似的方法来创建关联对象.但是,我们只是将连接对象添加到api中,而不是覆盖存储中的方法.

所以在我们创建的模型中:

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')
});
Run Code Online (Sandbox Code Playgroud)

然后,对于事务,我们只需更改并提交连接对象.

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();   
Run Code Online (Sandbox Code Playgroud)

});

API会创建一个HashtagUser对象,而follow方法只会将该用户添加到关联的部分.

对于删除,它会弹出关联的对象并销毁关联对象.

虽然它并不像它那样优雅,但我们的主要动机是,当Ember Data得到更新时,我们应该能够将它转换为简单的Ember Data支持版本,比我们与Store本身混淆时更容易.