在我的网络应用程序中,我有产品和购物清单。服务器提供REST端点。
GET /api/shopping-lists/abc
返回
{
shoppingList: {
id: "abc",
products: ["p123", "p234", "p345"]
}
}
在我的Ember 1.7.0
应用程序中,我使用Ember Data 1.0.0-beta.6
。我的模型看起来像这样:
App.ShoppingList = DS.Model.extend({
products: DS.hasMany("product", {async: true}),
});
App.Product = DS.Model.extend({
name: DS.attr("string")
});
因为我无法找到正确的信息" Ember way"添加和删除多对多关系中的记录,我正在这样的购物清单中添加和删除产品:
function addToShoppingList(shoppingList, toBeAddedProduct) {
shoppingList.get("products").then( function(products) {
products.pushObject( toBeAddedProduct );
shoppingList.save();
});
}
function removeFromShoppingList(shoppingList, toBeRemovedProduct) {
shoppingList.get("products").then( function(products) {
products.removeObject( toBeRemovedProduct );
shoppingList.save();
});
}
在上面的函数调用shoppingList.save()
时,Ember数据将发送一个PUT
请求,其中包含JSON有效内容,其中包含此购物清单中所有产品的ID:
addToShoppingList(abcShoppingList, p456Product);
//results in PUT on /api/shopping-lists/abc with payload:
{
"shoppingList" : {
"products" : ["p123", "p234", "p345", "p456"]
}
}
由于购物清单可能会变长,我宁愿只有一个增量更新,只包含购物清单的更改,即:
{
"shoppingList" : {
"products" : ["p456"]
}
}
我可以将Ember数据仅用于PUT
对记录的更改,而不是发送完整记录吗?
此外,removeFromShoppingList(..)
功能会将完整记录作为 PUT
请求发送。相反,我希望让它发送增量DELETE
请求。
答案 0 :(得分:1)
Ember Data允许您在适当的模型序列化器中以及适配器(如果需要)中实现构建json有效负载所需的任何内容。我建议查看JSONSerializer和RESTSerializer的Ember Data源代码,因为调整生成(序列化)和消耗(规范化)的JSON有很大的灵活性。
听起来你想要实现PATCH语义,但你可以用PUT做你想要的,只提供你的URL端点目标产品关系,例如/api/shopping-lists/123/products
。这与定位完整模型/api/shopping-lists/123
和PUTing仅仅是“products”数组不同,因为它不符合HTTP语义。
URL标识资源,并且该端点上的GET和PUT或DELETE可以幂地更新或删除单个属性甚至是值的子集,只要URL范围指向该属性或某个子集,它就是定义一个独特的资源,HTTP完全支持重叠资源,甚至多个资源受到PUT的影响。
因此,您可以将购物清单中的产品表示为单独的资源:/api/shopping-lists/123/:product-id
,只需使用DELETE删除和PUT即可创建/添加产品到列表中。许多URL设计都是可能的,包括如图所示的嵌套URL或使用复合键甚至代理键的URL,因此您必须考虑在您的服务器上最有效的方法。
您可以决定实施Ember数据连接模型,例如ShoppingListProduct
,以便更轻松地管理。然后,ShoppingListProduct将为ShoppingList和Product指定belongsTo
关系。您还可以从belongsTo关系生成'id'属性,以便DS Store标识映射按预期工作。在模型序列化器中实现这一点非常简单。
<强>更新强>
要在下面回答你的评论,遵循的一个好规则是将PUT视为REPLACE而不是UPDATE,这样你PUT就是你应该得到的东西,假设你的PUT没有其他任何东西修改了资源。如果这不是真的,那么可能表明您没有在URL上定义足够精细的粒度来确定要替换的内容,或者您可能应该考虑使用PATCH来仅定位您想要更改的属性。
我不知道本身是否存在“最佳实践”但我倾向于仅从具有外键的端点(即belongsTo端)更新资源。我通常最终得到一个加入资源,例如Taggings或Friendship,所以它只是通过belongsTo管理关系。这往往遵循您在关系数据库中的操作,因此它运行良好。