Ember.js &Ember 数据:如何在父子不存在时创建具有 hasMany 关系的记录 [英] Ember.js & Ember Data: How to create record with hasMany relationship when the parent and child don't exist yet

查看:14
本文介绍了Ember.js &Ember 数据:如何在父子不存在时创建具有 hasMany 关系的记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就像我使用 ember-data 所做的大多数事情一样,简单的测试用例非常简单,但是由于我缺乏理解(我认为文档),任何真实"的东西很快就会崩溃.在最简单的情况下,创建新记录并将其保存到我的 REST API 没有问题.我将使用流行的水果篮示例,并从保存一片新的 fruit 开始.

As seems to be the case with most everything I do with ember-data the simple test case is very simple but anything "real" falls apart quickly due to my lack of understanding (and I think documentation). In the simplest case I have no problem creating a new record and saving it to my REST API. I'll use the prevalent fruit basket example and start with just saving a new piece of fruit.

// Here is our fruit model
module.exports = App.Fruit= DS.Model.extend({
    name: attr('string'),   
    color: attr('string')
});

// This is easy to create and save
var fruit = this.store.createRecord('fruit', {
    name: 'apple',
    color: 'red'
});

fruit.save().then(successCallback, errorCallback);

好的,我这里没有问题.从概念上讲是有道理的,代码很干净,事情看起来很好!现在假设我们有一个 basket 模型,并且 basket 模型可以容纳很多 fruit.此外,用户可以通过 UI 一步创建新的 fruit 并将其添加到尚未创建的新 basket.

Okay, I have no problem here. Conceptually makes sense, the code is clean, and things look peachy! Now suppose that we have a basket model and that basket model can hold lots of fruit. Furthermore, the user can create new fruit and add it to a new basket that has not been created yet in one step from the UI.

这里是新模型:

module.exports = App.Fruit= DS.Model.extend({
    name: attr('string'),   
    color: attr('string')
    basket: DS.belongsTo('basket')
});

module.exports = App.Basket = DS.Model.extend({
    fruits: DS.hasMany('fruit', {async:true})
});

鉴于上述情况,假设用户输入了两个当前不存在于商店或后端 REST API 中的新水果,将它们添加到他的新篮子(也不存在)中,然后点击保存".

Given the above, lets say the user inputs in two new fruits that don't currently exist in the store or in the backend REST API, adds them to his new basket (which also doesn't exist yet) and then hits 'save'.

您如何使用 Ember Data 创建此记录?我希望你能做这样的事情:

How do you create this record using Ember Data? I was hoping you could do something like this:

var newFruits = Ember.A();

newFruits.pushObject(this.store.createRecord('fruit', {
    name: 'orange',
    color: 'orange'
}));

newFruits.pushObject(this.store.createRecord('fruit', {
    name: 'banana',
    color: 'yellow'
}));

var basket = this.store.createRecord('basket', {
    fruits: newFruits
});

basket.save().then(successCallback, errorCallback);

不幸的是,这似乎不起作用.当我在 Chrome 检查器中查看 POST 请求数据时,篮子的 fruits 属性始终为空.基本上,请求最终看起来是这样的:

Unfortunately, this doesn't seem to work. When I look at the POST request data in Chrome inspector the fruits property of basket is always empty. Basically, the request ends up looking this:

{
    basket: {
       fruits: []
    }
}

我是否使用正确的模式来创建篮子"记录?我希望我不必在保存篮子之前先保存每块水果,因为当 1 个就足够时发送 3 个 POST 请求似乎很浪费.另外,当用户想要创建 10 个水果时会发生什么?那将是 11 个 POST 请求.

Am I using the correct pattern to create the 'basket' record? I'm hoping I don't have to end up saving each piece of fruit first before saving the basket as it seems wasteful to send 3 POST requests when 1 would suffice. Additionally, what happens when the user wants to create 10 pieces of fruit? That would be 11 POST Requests.

是否有完成上述任务的标准做法?本质上,您如何创建一个具有 hasMany 关系(篮子)的新记录,其中 hasMany 关系中的记录也是新的(结果).

Is there a standard practice for accomplishing the above? Essentially, how do you create a new record with a hasMany relationship (basket) where the records in the hasMany relationship are also new (the fruit).

谢谢!

以下是我使用的版本:

------------------------------- 
Ember      : 1.3.2+pre.25108e91 
Ember Data : 1.0.0-beta.7+canary.238bb5ce 
Handlebars : 1.3.0 
jQuery     : 2.0.3 
------------------------------- 

推荐答案

我只是自己解决这个问题,但我就是这样做的,而且效果很好……

I'm just figuring this out myself, but I just did it this way and it works…

对于初学者来说,当您 this.store.createRecord('basket', {}) 时,它的 fruits 属性应该带有一个空数组.所以,这样做:

For starters, when you this.store.createRecord('basket', {}) it should come with an empty array for its fruits property. So, do this:

var basket = this.store.createRecord('basket', {});

basket.get('fruits').addObject(this.store.createRecord('fruit', {
    name: 'orange',
    color: 'orange'
}));

basket.get('fruits').addObject(this.store.createRecord('fruit', {
    name: 'banana',
    color: 'yellow'
}));

顺便说一下,空的 fruits 数组实际上是一个 DS.PromiseArray(它可能会立即解析为一个 DS.ManyArray?),一个Ember.Array 的更具体的子类,所以这可能会有所作为.

Incidentally, the empty fruits array is actually a DS.PromiseArray (which may instantly resolve to a DS.ManyArray?), a more specific subclass of Ember.Array, so that could make a difference.

然而,我发现 fruits 属性根本不会被序列化——不过我使用的是 JsonApiAdapter,所以 可能 是原因.或者这可能是 hasMany 子对象尚未持久化时的预期行为.无论如何,我只是在我的控制器的 actions.save 方法中做了这样的事情:

However, what I found was that the fruits property wouldn't get serialized at all--I'm using the JsonApiAdapter though, so that could be the reason. Or it might be that this is the expected behavior when the hasMany child objects haven't been persisted yet. Anyway, I just did something like this in my controller's actions.save method:

basket.save().then(function(){
    var promises = Ember.A();
    basket.get('fruits').forEach(function(item){
        promises.push(item.save());
    });
    Ember.RSVP.Promise.all(promises).then(function(resolvedPromises){
        alert('All saved!');
    });
});

不知何故,神奇的是,当所有这些都完成后,我最终得到了一个保存的篮子",带有生成的 id,并保存了带有生成的 id 的水果"s.而且,所有水果的 belongsTo 属性都指向篮子,篮子的 hasMany 包含所有水果……尽管事实上,当我 save()d 篮子,我后端的响应为我的 fruits 属性返回了一个空数组,我确信这会搞砸,但不知何故没有.

Somehow, magically, when all that was done, I ended up with a saved "basket", with a generated id, and saved "fruits" with generated ids. And, all the fruits' belongsTo properties pointed back at the basket, and the basket's hasMany contained all the fruits…despite the fact that, when I save()d the basket, the response from my backend returned an empty array for my fruits property, which I was sure would mess things up but somehow didn't.

当然,这些不是我的实际模型,但相似度非常接近.我正在使用 Ember Data 1.0.0-beta5 和 Ember 1.3.1.我没有使用库存的 REST 适配器,但 JsonApiAdapter 是一个非常薄的外壳——所以试试这个方法,看看它是否有效!

Of course, these weren't my actual models, but the parallel was very close. I'm on Ember Data 1.0.0-beta5 and Ember 1.3.1. I'm not using the stock REST adapter, but the JsonApiAdapter is a pretty thin shell over it--so try this approach and see if it works!

我在此处打开了一个类似的问题 解决了我在使用上述代码更新现有记录(而不是创建新记录)时遇到的问题.该解决方案更通用、更详细,但也更复杂.

I've opened a similar question here that addresses a problem I encountered using the above code to also update existing records (as opposed to creating new ones). That solution is more general and detailed but more complex.

此外,我遇到的另一个潜在问题是,当(在本例中)创建 basket 时,fruits 属性(这是一个 DS.PromiseArray) 可能还没有完全准备好.所以你可能需要这样做:

Also, another potential gotcha I ran into is that when (in this example) the basket is created, the fruits property (which is a DS.PromiseArray) may not be fully ready yet. So you may need to do it like this instead:

var basket = this.store.createRecord('basket', {});

basket.get('fruits').then(function(){
    // Now the fruits array is available
    basket.get('fruits').addObject(this.store.createRecord('fruit', { /* ... */ }));
});

这篇关于Ember.js &Ember 数据:如何在父子不存在时创建具有 hasMany 关系的记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆