web-dev-qa-db-ja.com

Ember.js&Ember Data:親と子がまだ存在しないときにhasMany関係でレコードを作成する方法

私がember-dataで行うほとんどすべての場合に当てはまるように、単純なテストケースは非常に単純ですが、「本当の」ものは私の理解不足のためすぐにバラバラになります(そしてドキュメントだと思います)。最も単純なケースでは、新しいレコードを作成し、それをREST APIに保存しても問題ありません。よく使われているフルーツバスケットの例を使用して、新しい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を保持できると仮定します。さらに、ユーザーは新しいfruitを作成し、UIから1ステップでまだ作成されていない新しいbasketに追加できます。

新しいモデルは次のとおりです。

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に現在存在しない2つの新しいフルーツに入力し、それらを新しいバスケット(まだ存在しない)に追加してから、 「保存」を押します。

Emberデータを使用してこのレコードをどのように作成しますか?私はあなたがこのような何かをすることができることを望んでいました:

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

残念ながら、これはうまくいかないようです。 POSTインスペクターのChromeリクエストデータを見ると、バスケットのfruitsプロパティは常に空です。基本的に、リクエストは次のようになります。

{
    basket: {
       fruits: []
    }
}

正しいパターンを使用して「バスケット」レコードを作成していますか?バスケットを保存する前に、果物を1つずつ保存する必要がなくなることを望んでいます。1つで十分な場合に3つのPOSTリクエストを送信するのは無駄に思えます。さらに、ユーザーが10個の果物を作成したい場合はどうなりますか?それは11 POSTリクエストです。

上記を達成するための標準的なプラクティスはありますか?基本的に、hasMany関係のレコードも新規であるhasMany関係(バスケット)で新しいレコードをどのように作成しますか(フルーツ)。

ありがとうございました!

私が使用しているバージョンは次のとおりです。

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

私は自分でこれを理解しているだけですが、この方法でそれをやっただけで機能します...

まず、this.store.createRecord('basket', {})を実行すると、fruitsプロパティに空の配列が必要です。だから、これを行う:

_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_のより具体的なサブクラスです。差。

しかし、私が見つけたのは、fruitsプロパティがまったくシリアル化されないということです。ただし、JsonApiAdapterを使用しているため、could理由である。または、hasMany子オブジェクトがまだ永続化されていない場合、これが予期される動作である可能性があります。とにかく、コントローラーのactions.saveメソッドで次のようなことをしました。

_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、および生成されたidsで「果物」が保存されました。そして、すべての果物のbelongsToプロパティはバスケットを指しており、バスケットのhasManyにはすべての果物が含まれていました…私がバスケットをsave() d私のバックエンドからの応答はfruitsプロパティに対して空の配列を返しました。これは物事を混乱させると確信していましたが、どういうわけかそうではありませんでした。

もちろん、これらは私の実際のモデルではありませんでしたが、類似点は非常に近かったです。 Ember Data 1.0.0-beta5およびEmber 1.3.1を使用しています。ストックRESTアダプターを使用していませんが、JsonApiAdapterはかなり薄いシェルです。このアプローチを試して、動作するかどうかを確認してください。

編集

同様の質問 を開きました。これは、上記のコードを使用して既存のレコードも更新する(新しいレコードを作成するのではなく)ことで発生した問題に対処します。このソリューションは、より一般的かつ詳細ですが、より複雑です。

また、(この例では)basketが作成されたときに、fruitsプロパティ(_DS.PromiseArray_)がまだ完全に準備されていない可能性があります。そのため、代わりに次のようにする必要があります。

_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', { /* ... */ }));
});
_
26
S'pht'Kr

他の誰かがこれに遅れている場合、現在のドキュメントでは、次のようにcreateRecord()を単純に呼び出すことができると指摘しています。

post.get('comments').createRecord({})

postが空のオブジェクトであっても機能します。

17