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

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

问题描述

由于我不了解(我认为文档),所以简单的测试用例很简单,但任何真实的都会快速崩溃。在最简单的情况下,创建新记录并将其保存到我的REST API中没有问题。我会使用流行的水果篮子的例子,只需保存一个新的水果

  //这是我们的水果模型
module.exports = App.Fruit = DS.Model.extend({
name:attr('string'),
color:attr('string')
});

//这很容易创建并保存
var fruit = this.store.createRecord('fruit',{
name:'apple',
color :'red'
});

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

好的,我没有问题。在概念上是有道理的,代码是干净的,东西看起来是桃红色的!现在假设我们有一个篮子模型,而 basket 模型可以容纳大量 / code>。此外,用户可以创建新的水果,并将其添加到尚未在一步中创建的新的购物篮



所以这里是新的模型:

  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,将它们添加到他的新购物篮(也不存在),然后点击保存。



你如何创建这个使用Ember Data记录?我希望你可以这样做:

  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请求数据时,basket的 fruit 属性始终为空。基本上,请求最终看起来是这样的:

  {
basket:{
fruits:[]
}
}

我使用正确的模式创建篮子记录?我希望在保存篮子之前,最先不要先保存每个水果,因为当1满足时,发送3个POST请求似乎很浪费。此外,当用户想要创建10件水果时会发生什么?这将是11个POST请求。



是否有完成上述的标准做法?基本上,你如何用hasMany关系(篮子)创建一个新记录,其中hasMany关系中的记录也是新的(水果)。



谢谢! / p>

以下是我使用的版本:

  ---- --------------------------- 
Ember:1.3.2 + pre.25108e91
Ember数据:1.0.0 -beta.7 + canary.238bb5ce
手柄:1.3.0
jQuery:2.0.3
-------------------- -----------


解决方案

我只是想弄清楚自己,但我只是这样做,它的作品...



对于初学者,当你 this.store。 createRecord('basket',{})它应该为 fruit 属性设置一个空数组。所以,这样做:

  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'
}));

顺便提一句,空的水果一个 DS.PromiseArray (可以立即解析为一个 DS.ManyArray ?),一个更具体的 Ember.Array ,这样可能会有所作为。



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

  basket.save()然后(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的水果。而且,所有的水果'code> belongsTo 属性指向篮子,篮子的 hasMany 包含所有的水果...尽管事实上,当我 save() d时,我的后端的回复为我的水果返回一个空数组财产,我肯定会混乱,但不知何故没有。



当然,这些不是我的实际模型,但并行非常接近。我在Ember Data 1.0.0-beta5和Ember 1.3.1上。我没有使用库存REST适配器,但JsonApiAdapter是一个非常薄的shell,所以尝试这种方法,看看它是否可行!



编辑



我已经打开了一个类似的问题,解决了我遇到的使用上述代码来更新现有记录(而不是创建新的记录)的问题。这个解决方案比较笼统,详细但更复杂。



另外我碰到的另一个潜在问题是,当(在这个例子中) 创建,水果属性(这是一个 DS.PromiseArray )可能不是完全准备好了所以你可能需要这样做:

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

basket.get('fruits')然后(function(){
//现在水果数组可用
basket.get('fruits')。addObject this.store.createRecord('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);

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.

So here are the new models:

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

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'.

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);

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: []
    }
}

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.

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).

Thank you!

Here are the versions I am using:

------------------------------- 
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…

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'
}));

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.

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!');
    });
});

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.

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!

Edit

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.

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天全站免登陆