Ember.js 对余烬数据多对多关系的增量更改

Ember.js 对余烬数据多对多关系的增量更改,ember.js,ember-data,Ember.js,Ember Data,在我的web应用程序中,我有产品和购物清单。服务器提供REST端点 GET /api/shopping-lists/abc 返回 { shoppingList: { id: "abc", products: ["p123", "p234", "p345"] } } 在我的Ember 1.7.0应用程序中,我使用Ember数据1.0.0-beta.6。我的模型是这样的: App.ShoppingList = DS.Model.extend({ products:

在我的web应用程序中,我有产品和购物清单。服务器提供REST端点

GET /api/shopping-lists/abc
返回

{
  shoppingList: {
    id: "abc",
    products: ["p123", "p234", "p345"]
  }
}
在我的
Ember 1.7.0
应用程序中,我使用
Ember数据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")
});
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();
    });

}
由于我找不到关于从多对多关系中添加和删除记录的正确“余烬方式”的规范信息,我正在向购物列表添加和删除产品,如下所示:

App.ShoppingList = DS.Model.extend({
    products: DS.hasMany("product", {async: true}),
});

App.Product = DS.Model.extend({
    name:  DS.attr("string")
});
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()
时,余烬数据将发送一个带有JSON有效负载的
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"]
    }
}
我是否可以只将余烬数据设置为
PUT
a记录的更改,而不是发送完整记录


另外,
removeFromShoppingList(..)
功能将以
PUT
请求的形式发送完整记录。相反,我更希望它发送一个增量
删除
请求。

余烬数据允许您在适当的模型序列化程序和适配器(如果需要)中实现构建json负载所需的任何功能。我建议查看JSONSerializer和RESTSerializer的Ember数据源代码,因为对生成(序列化)和使用(规范化)的JSON进行调优有很大的灵活性

听起来你想实现补丁语义,但是你可以通过PUT做你想做的事情,提供你的URL端点只针对产品关系,例如
/api/shopping list/123/products
。这不同于针对完整模型
/api/shopping list/123
,而只放置“products”数组,因为这不符合HTTP语义

URL标识资源,该端点上的GET和PUT或DELETE可以幂等地仅更新或删除单个属性,甚至是值的子集,只要URL作用于该属性或某个子集,根据定义,它是一种独特的资源,HTTP完全支持重叠的资源,甚至支持受PUT影响的多个资源

因此,进一步讲,您可以将购物列表中的产品表示为单独的资源:
/api/shopping list/123/:product id
,只需使用DELETE删除并放置即可创建/添加产品到列表中。许多URL设计是可能的,包括嵌套的URL,如图所示,或使用复合键或代理键的那些URL,因此您将不得不考虑在服务器上工作最有效的。 您可以决定实现一个Ember数据连接模型,例如
ShoppingListProduct
,以使其更易于管理。然后,ShoppingListProduct将指定ShoppingList和Product的
belongsTo
关系。您还可以从两个belongsTo关系中创建“id”属性,以便DS存储标识映射按预期工作。在模型序列化程序中实现这一点很简单

更新

要回答您在下面的评论,一个很好的遵循规则是将PUT视为替换而不是更新,这样您所放置的内容就是您应该得到的内容,假设自您放置以来没有其他内容修改过资源。如果这不是真的,它可能是一个指示,你没有定义一个足够好的粒度在你的URL范围内,你正在替换,或者你应该考虑使用补丁目标只是你想要改变的属性。
我不知道是否有“最佳实践”本身,但我倾向于只从具有外键的端点(即belongsTo端)更新资源。多对多关系我通常以加入资源(如标记或友谊)结束,所以它只是通过belongsTo再次管理关系。这往往遵循您在关系数据库中所做的操作,因此它工作得很好。

不,您不能。这是您保存shoppingList模型的唯一时间吗?@Kingpin2k、
添加到shoppingList(…)
从shoppingList(…)
是我的代码中当前唯一可以修改
shoppingList
产品关系的地方。我一直在考虑在不依赖余烬数据的情况下自己处理定制请求和记录更新,但我猜余烬数据附带了这种开箱即用的功能……只需手动处理,就会更容易。我不知道还有哪一个客户端ORM会像你所说的那样进行增量更新。我不知道为什么我的答案被否决了,一个原因是考虑到答案中的大量考虑,基本礼貌。回答很好。我想知道添加和删除资源之间关系的正确RESTful方式是什么<代码>补丁
似乎增加了一种额外的方式。。。附注:为什么
PUT
ting a
products
-在
/api/shopping list/123
上的JSON有效负载不被鼓励?更新了答案,提供了一些关于管理关系和REST/PUT的指导