EmberData: Two models related with hasMany relationships

后端 未结 2 1726
滥情空心
滥情空心 2021-02-03 15:55

I have an application logic that requires two models to have reciprocal hasMany relationships. As an example, imagine a set of GitHub issues that can be tagged with several labe

2条回答
  •  温柔的废话
    2021-02-03 16:10

    Many to Many relationships are not yet supported in ember-data. For the moment, one possible workaround is to manually manage the join table.

    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'); 
      }
    });
    

    This is just the starting point. You need then to customize your models and adapter in order to send/receive/persist records in a working manner

    For example, in our app, we introduce an { includedJoin: true } option inside the hasMany relations, and declare the join table as a JoinModel

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

    Then in the Adapter, we override the create/update/delete methods in order to ignore the joins table lifecycle in the store

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

    Finally, in the serializer, we override the addHasMany function in order to send the join data to the server as embedded ids in the parent models.

    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;
      }
    }
    

    Server-side we are using Rails with ActiveModelSerializer, so the only little-tricky-customization is when when we update the parent models, we manually manage the joins relation, and create/delete entries in the join table.

提交回复
热议问题