2013-12-21 79 views
12

我需要一次将所有深层对象保存到服务器,并且无法在线查找任何使用最新的支持数据(1.0.0-beta.4)的示例。Ember数据:保存关系

例如,有这些模特: (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" 
    } 
} 

我是否必须手动保存玩具t OO?反正是有,我可以把它发送下面的JSON到服务器:

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

或者

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

见的jsfiddle:http://jsfiddle.net/jgillick/LNXyp/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/

+0

使用Ember 1.3.1/data 1.0.0-beta 6,'property = Ember.get(record,key)'似乎返回一个空的promise数组。这特别奇怪,因为我可以用'record.get('key')。然后(函数(items){...})'访问子记录'。任何想法,如果这是一个已知的问题? – eriknelson

3

玩具不能同时异步和始终嵌入,那些是相互矛盾的选择。嵌入式仅存在于当前活动模型序列化器中。

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

玩具是多对一的关系,因为在属于关联方存在的关系会更有效玩具的保存过程中保存的关系。这就是说,如果你一次创建它,那么就想把它保存在一个大块中,这是压倒一切的地方。

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); 
    }); 
+0

“玩具”在哪里定义?如果你的意思是'child.get('toys')。save()',或者访问promise的响应,那么这个调用是否保存在每一行上独立的模型或一次性保存它们? 我和Jeremy有同样的问题,当我尝试调试/检查hasMany属性时,就像在这种情况下查看child.get('toys'),即使在我推送新记录之后,数组中的值为空。我认为这是因为Ember-Data知道将玩具的ID存储在玩具数组中,但玩具没有ID,因为它没有被保存。 –

+0

是的,那应该是'玩具',我是保存个人玩具。 – Kingpin2k

+0

所以,如果我正确理解这一点。我们已经建立了模型与一对多的关系,孩子有许多玩具,玩具属于孩子。在内部,玩具模型上会有一个'childId'属性,这个属性实际上会被持久化。 当您调用'child.pushObject(玩具)'时,两者之间的关系建立并且一旦孩子被保存,玩具的childId属性会自动更新? 我期待着你必须在promise履行处理函数里面调用'toy.set('child',response)'。 –

8

这里的答案是过时的。 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') 
}); 

您可以定义自定义序列为您的孩子型号:

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

这告诉灰烬数据,你想“玩具”到作为'孩子'有效载荷的一部分被包括在内。从您的API的HTTP GET响应应该是这样的:

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

当你保存你的模型,子玉的数据将发送该服务器:

{ 
    "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,当您单击“保存”按钮,你就需要使用开发检查,以查看在发送到服务器的请求。

+0

你知道这是否是首选的方法吗?我的理解是,在GET响应中包含嵌入式记录并不总是最有效的。但是,我可以看到嵌入记录在POST/PUT请求中的好处。 – antony

+1

@antony,你在问一个API设计问题,它不是专门关于Ember Data的。如果您认为汇总(例如订单有订单项目,但订单项目本身没有标识),则您需要使用嵌入式记录。此外,如果您需要在一个原子事务中发生更新(例如再次订购和订购商品),那么您将需要使用嵌入式记录。但是,如果每个模型都有自己可识别的端点,那么嵌入式记录就没有意义。 –