Ember数据:保存关系

时间:2013-12-21 02:43:54

标签: json ember.js ember-data

我需要一次性将一个深层对象保存到服务器,并且无法在线找到任何使用最新ember数据(1.0.0-beta.4)的示例。

例如,使用这些模型: (jsfiddle

App.Child = DS.Model.extend({
    name: DS.attr('string'),
    age: DS.attr('number'),
    toys: DS.hasMany('toy', {async:true, embedded:'always'}),
});
App.Toy = DS.Model.extend({
    name: DS.attr('string'),
    child: DS.belongsTo('child')
});

这段代码:

actions: {
    save: function(){
        var store = this.get('store'),
            child, toy;

        child = store.createRecord('child', {
            name: 'Herbert'
        });
        toy = store.createRecord('toy', {
            name: 'Kazoo'
        });

        child.set('toys', [toy]);
        child.save();
    }
}  

它只保存子对象的JSON,但不保存任何玩具 - 甚至没有侧载:

{
  child: {
    age: null
    name: "Herbert"
  }
}

我是否还必须手动保存玩具?无论如何,我可以让它将以下JSON发送到服务器:

{
  child: {
    age: null
    name: "Herbert",
    toys: [{
        name: "Kazoo"
    }]
  }
}

或者

{
  child: {
    age: null
    name: "Herbert",
    toys: [1]
  }
}

参见JSFiddle:http://jsfiddle.net/jgillick/LNXyp/2/

3 个答案:

答案 0 :(得分:9)

这里的答案已经过时了。 Ember Data现在支持嵌入式记录,这使您可以完成您正在寻找的事情,即在一个大的有效负载中获取和发送完整的对象图。例如,如果您的模型设置如下:

App.Child = DS.Model.extend({
    name: DS.attr('string'),
    age: DS.attr('number'),
    toys: DS.hasMany('toy')
});
App.Toy = DS.Model.extend({
    name: DS.attr('string'),
    child: DS.belongsTo('child')
});

您可以为您的Child模型定义自定义序列化程序:

App.ChildSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
  attrs: {
    toys: {embedded: 'always'}
  }
});

这告诉Ember Data你喜欢玩具'被列为“孩子”的一部分。有效载荷。您的API的HTTP GET响应应如下所示:

{
  "child": {
    "id": 1,
    "name": "Todd Smith",
    "age": 5,
    "toys": [
      {"id": 1, "name": "boat"},
      {"id": 2, "name": "truck"}
    ]
  }
}

当您保存模型时,Ember Data会将其发送到服务器:

{  
   "child":{  
      "name":"Todd Smith",
      "age":5,
      "toys":[  
         {  
            "id":"1",
            "name":"boat",
            "child":"1"
         },
         {  
            "id":"2",
            "name":"truck",
            "child":"1"
         }
      ]
   }
}

这是一个证明这一点的JSBin。

http://emberjs.jsbin.com/cufaxe/3/edit?html,js,output

在JSbin中,当您点击'保存'按钮,您需要使用Dev Inspector查看发送到服务器的请求。

答案 1 :(得分:3)

玩具不能同时是异步和嵌入,这些都是矛盾的选择。嵌入式仅存在于当前的活动模型序列化程序中。

toys: DS.hasMany('toy', {embedded:'always'})

玩具是ManyToOne关系,并且由于关系存在于belongsTo方面,因此在玩具保存期间保存关系更有效。话虽这么说,如果你是一次性创建它,那么就想把它保存在一个大块中,这是重写发挥作用的地方。

serializeHasMany: function(record, json, relationship) {
  var key = relationship.key;

  var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);

  if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany' ||
      relationshipType === 'manyToOne') {
    json[key] = get(record, key).mapBy('id');
    // TODO support for polymorphic manyToNone and manyToMany relationships
  }
 },

你的保存应该是这样的

    var store = this.get('store'),
        child, toy;

    child = store.createRecord('child', {
        name: 'Herbert'
    });
    toy = store.createRecord('toy', {
        name: 'Kazoo'
    });

    child.get('toys').pushObject(toy);
    child.save().then(function(){
       toy.save();
    },
    function(err){
      alert('error', err);
    });

答案 2 :(得分:0)

我需要一个深层物体,而不是侧面物体,所以基于kingpin2k的答案,我想出了这个:

DS.JSONSerializer.reopen({
    serializeHasMany: function(record, json, relationship) {
        var key = relationship.key,
            property = Ember.get(record, key),
            relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);

        if (property && relationshipType === 'manyToNone' || relationshipType === 'manyToMany' ||
            relationshipType === 'manyToOne') {

            // Add each serialized nested object
            json[key] = [];
            property.forEach(function(item, index){
                json[key].push(item.serialize());
            });
        }
    }
});

现在,当您致电child.serialize()时,它将返回此对象:

{
  child: {
    name: "Herbert",
    toys: [
      {
        name: 'Kazoo'
      }
    ]
  }
}

这就是我需要的。以下是jsfiddle的实际应用:http://jsfiddle.net/jgillick/LNXyp/8/