我很难在ember数据中保存一对多的关系。我有这样的关系:
App.ParameterSet = DS.Model
name: DS.attr("string")
regions: DS.hasMany("App.Region")
App.Region = DS.Model
name: DS.attr("string")
如果我要做这样的事情:
parameterSet = App.ParameterSet.find(5)
@transaction = @get("store").transaction()
@transaction.add(parameterSet)
region1 = App.Region.find(10)
region2 = App.Region.find(11)
parameterSet.set("name", "foo")
parameterSet.get("regions").pushObject(region)
@transaction.commit()
然后我希望看到带有这样的有效负载的PUT请求:
api/ParameterSets/5
{parameterSet: {name: "foo", regionIds:[10, 11]}}
但我得到了这个:
{parameterSet: {name: "foo"}}
我不关心从孩子到父母之间的关系,但如果我将parameterSet: DS.belongsTo("App.ParameterSet")
添加到App.Region模型,那么我会向两个新关系获取2个PUT请求到区域url我想要的是。
我想这是一个多对多的关系,我不确定它是否支持,但有关如何实现我所描述的任何想法?感谢
答案 0 :(得分:8)
hasMany
关系的序列化由addHasMany()
的{{1}}方法处理。
以下注释包含在source code:
中默认的REST语义只是添加有多个关系 嵌入式。如果最初通过ID加载关系,我们会假设 这是作为性能优化完成的,并且改变了 has-many应保存为子项所属的外键更改 关系。
要实现您的目标,一个选项是指示关系应该嵌入适配器中。
json_serializer.js
当然,现在你的后端需要在参数集的JSON中实际嵌入关联区域的JSON。如果您想保持原样,只需使用自定义序列化覆盖App.Store = DS.Store.extend({
adapter: DS.RESTAdapter.extend({
serializer: DS.RESTSerializer.extend({
init: function() {
this._super();
this.map('App.ParameterSet', {
regions: { embedded: 'always' }
});
}
})
})
});
。
addHasMany()
答案 1 :(得分:2)
我无法在ahmacleod的答案中添加注释,但除了我注意到在修改子记录时父记录没有被标记为脏时,它是现场的。在问题的示例中,不会出现问题,因为父记录上也修改了名称。
但是,一般情况下,如果您要遵循ahmacleod的第二个答案,则需要覆盖RESTAdapter上的dirtyRecordsForHasManyChange方法。否则,永远不会调用序列化程序中的addHasMany,因为记录甚至没有标记为脏。
现有方法如下:
dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) {
var embeddedType = get(this, 'serializer').embeddedType(record.constructor, relationship.secondRecordName);
if (embeddedType === 'always') {
relationship.childReference.parent = relationship.parentReference;
this._dirtyTree(dirtySet, record);
}
},
所以我想你会想要这样的东西:
App.Store = DS.Store.extend({
adapter: DS.RESTAdapter.extend({
dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) {
relationship.childReference.parent = relationship.parentReference;
this._dirtyTree(dirtySet, record);
},
serializer: DS.RESTSerializer.extend({
addHasMany: function(hash, record, key, relationship) {
// custom ...
}
})
})
});