Ember.js EmberData:两个与多个关系相关的模型

Ember.js EmberData:两个与多个关系相关的模型,ember.js,ember-data,Ember.js,Ember Data,我有一个应用程序逻辑,需要两个模型具有许多关系。例如,设想一组GitHub问题可以用几个标签进行标记 我正在尝试使用扩展默认RESTAdapter的适配器。所有应用程序都可以正常工作,但double-hasMany关系引发异常。深入研究代码,一个方法inverseBelongsToForHasMany会抛出一个异常 所以,我猜Ember.Data不支持两个模型之间的关联,因为这两个模型在双方都有很多关系,每个hasMany都需要一个关联的belongsTo。我的问题是: 这是否得到支持,而问题只

我有一个应用程序逻辑,需要两个模型具有许多关系。例如,设想一组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({})
    使用带下划线的外键。