在序列化修改的记录时,belongsTo promise是未定义的

时间:2014-03-07 09:09:32

标签: serialization ember-data

好的强制性信息:

DEBUG: ------------------------------- 
DEBUG: Ember      : 1.3.1 
DEBUG: Ember Data : 1.0.0-beta.7.f87cba88 
DEBUG: Handlebars : 1.0.0 
DEBUG: jQuery     : 1.10.2 
DEBUG: ------------------------------- 

以下是相关模型:

App.Destination = DS.Model.extend({
    label: DS.attr('string'),
    destinationMatchRules: DS.hasMany('destinationMatchRule', { async: true }),
    chargeRules: DS.hasMany('chargeRule', { async: true }),
});

App.ChargeRule = DS.Model.extend({
    startDate: DS.attr('date'),
    endDate: DS.attr('date'),
    costPerMinute: DS.attr('number'),
    countryCode: DS.attr('string'),
    label: DS.attr('string'),
    connectionCost: DS.attr('number'),
    destination: DS.belongsTo('destination', { async: true }),
});

App.DestinationMatchRule = DS.Model.extend({
    pattern: DS.attr('string'),
    priority: DS.attr('number'),
    destination: DS.belongsTo('destination', { async: true }),
});

我有一个destination.edit路由/控制器/模板,可以让我一起创建或编辑这些。如果我从头开始创建一个新集并将它们全部挂起,我使用此代码来保存所有内容:

save: function() {
    var destination = this.get('content');
    destination.save().then(function(){
        var promises = Ember.A();
        destination.get('destinationMatchRules').forEach(function(item){
            promises.push(item.save());
        });
        destination.get('chargeRules').forEach(function(item){
            promises.push(item.save());
        });
        Ember.RSVP.Promise.all(promises).then(function(resolvedPs){
            alert('All saved!');
        });
    });
}

它有效!并且非常高兴。

然而。如果我使用相同的路线和代码编辑现有图表 - 比如我编辑目的地的标签和/或destinationMatchRule的优先级 - 我对两个belongsTo('destination', { async: true })关系都有很大的问题。 / p>

我在序列化程序的serializeBelongsTo方法和我的save方法中添加了断点。似乎发生了以下情况:

  1. 如果DestinationMatchRule中的ChargeRulehasMany对象不是新创建的记录,则在.save()记录上调用Destination会自动尝试将记录保存在hasMany中,因此在此情况下,我的item.save()方法中的显式子记录save调用将被抢占。 (我认为......这是我不太确定的一部分)
  2. 当为serializeBelongsToDestinationMatchRule记录调用序列化程序的ChargeRule方法时,每个记录的destination属性为DS.PromiseObject承诺未解决。这会导致serializeBelongsTo向JSON对象添加destination: undefined,并最终在destination属性 中完全从发送到后端的序列化JSON中删除

    当然,这会导致我的后端认为子记录的destination对象已被删除(在我的情况下会导致基数违规)。

    当我将记录语句放在明确的item.save()电话附近时,我发现DS.PromiseObject 已经解决,这就是为什么我总结我所描述的内容#1以上。我首先尝试以Ember.run.next回调的方式包装这些调用,试图让belongsTo时间得到解决,但是如果我对#1这是正确的,那么无论如何都无济于事。但这也意味着我没有地方可以解决这个问题!

    有人可以帮我解决这个问题 - 我非常接近,我认为这可能是让Ember Data实际运作并用于“野心勃勃”的Web应用程序的最后一战。

    修改

    更正,我对此处操作顺序的结论不正确。实际上,我可以使其适用于新创建的图形并通过使save方法看起来像这样编辑现有图形:

    save: function() {
        var destination = this.get('content');
        destination.save().then(function(){
            //var promises = Ember.A();
            destination.get('destinationMatchRules').forEach(function(item){
                item.get('destination').then(function(){
                    item.save();
                });
                    //promises.push(item.save());
            });
            destination.get('chargeRules').forEach(function(item){
                item.get('destination').then(function(){
                    item.save();
                });
            });
            //Ember.RSVP.Promise.all(promises).then(function(resolvedPs){
            //    alert('All saved!');
            //});
        });
    }
    

    但是,这不能很好地扩展:如果我有更多的belongsTo关系怎么办?可能他们都要解决?此外,现在很难判断整个操作何时完成 - 我无法将item.save()返回的promise添加到我的promises数组中,因为它不是立即创建的(在评论中提示此欢迎)。并且,我应该then我没有看到的其他承诺,以确保destination.save()真的真的完成,并且所有关系都已传播?

1 个答案:

答案 0 :(得分:1)

现在发布作为答案似乎是一个很好的通用解决方案。但如果这是必要的,我真的很想知道是否有一种方法已经在代码中更简洁地处理它并且我复制了一些东西...

尽管如此,我正在努力解决这个问题,我在DS.Model上创建了一个名为saveWhenSettled的新方法,该方法返回Promise

DS.Model.reopen({
  saveWhenSettled: function() {
    var record = this;
    return new Ember.RSVP.Promise(function(resolve, reject){
      var promises = Ember.A();
      record.eachRelationship(function(rel){ 
        if(record.get(rel).then) promises.pushObject(record.get(rel));
      });
      Ember.RSVP.Promise.all(promises).then(function(){
        record.save().then(function(result){
          resolve(result);
        }, function(reason){
          reject(reason);
        });
      }, function(reason){
        reject(reason);
      });
    });
  }
});

现在我可以:

save: function() {
    var destination = this.get('content');
    destination.save().then(function(){
        var promises = Ember.A();
        destination.get('destinationMatchRules').forEach(function(item){
            promises.push(item.saveWhenSettled());
        });
        destination.get('chargeRules').forEach(function(item){
            promises.push(item.saveWhenSettled());
        });
        Ember.RSVP.Promise.all(promises).then(function(resolvedPs){
            alert('All saved!');
        });
    });
}

所以我收到完成通知,它会自动处理需要解决的记录上的多个关系(自发布问题以来我已经遇到过)。

同样,我希望有人告诉我,我已经复制了基线代码,我应该采取另一种方式。

可能会使用类似的方法来概括我的save方法,以便首先自动保存所有子关系,但我会将其作为读者的练习。