2013-02-28 53 views
9

我很難在餘燼數據中保存一對多的關係。我有這樣的關係:Ember數據保存了一段關係

App.ParameterSet = DS.Model 
    name: DS.attr("string") 
    regions: DS.hasMany("App.Region") 

App.Region = DS.Model 
    name: DS.attr("string") 

如果我做這樣的事情:

parameterSet = App.ParameterSet.find(5) 
@transaction = @get("store").transaction() 
@transaction.add(parameterSet) 
region1 = App.Region.find(10) 
region2 = App.Region.find(11) 
parameterSet.set("name", "foo") 
parameterSet.get("regions").pushObject(region) 
@transaction.commit() 

然後我希望看到與有效載荷的PUT請求是這樣的:

api/ParameterSets/5 

{parameterSet: {name: "foo", regionIds:[10, 11]}} 

但我卻得到了這個:

{parameterSet: {name: "foo"}} 

我不在乎從孩子到父母的關係,但是如果我將parameterSet: DS.belongsTo("App.ParameterSet")添加到App.Region模型中,那麼我會得到2個PUT請求到這兩個新關係的區域網址,這實際上並不是我想要的。

我想這是一個多對多的關係真的,我不確定是否支持,但有關如何實現我所描述的任何想法?謝謝

回答

8

hasMany關係的序列化由addHasMany()方法json_serializer.js處理。

以下注釋包含在source code

默認REST語義是,如果它 嵌入只添加一個具有一對多的關係。如果關係最初是通過ID加載的,我們假設 作爲性能優化完成,並且對 的更改有許多應該保存爲子項所屬的外鍵更改 - 關係。

要實現你想要的,一個選項是表明該關係應該嵌入到你的適配器中。

App.Store = DS.Store.extend({ 
    adapter: DS.RESTAdapter.extend({ 
    serializer: DS.RESTSerializer.extend({ 
     init: function() { 
     this._super(); 
     this.map('App.ParameterSet', { 
      regions: { embedded: 'always' } 
     }); 
     } 
    }) 
    }) 
}); 

當然,現在您的後端需要實際將相關區域的JSON嵌入到參數集的JSON中。如果你想保持原樣,你可以簡單地用自定義序列覆蓋addHasMany()

App.Store = DS.Store.extend({ 
    adapter: DS.RESTAdapter.extend({ 
    serializer: DS.RESTSerializer.extend({ 
     addHasMany: function(hash, record, key, relationship) { 
     // custom ... 
     } 
    }) 
    }) 
}); 
+0

大,感謝幫助了很多 – Charlie 2013-03-01 15:55:15

+0

這是非常有幫助,謝謝!我認爲這是一個非常短視的假設燼數據製作! – KOGI 2013-03-05 19:21:53

+0

這個「優化」的推理是什麼?我可以看到它在加載過程中是一種優化,但它在保存期間如何提供幫助?如果我想向父對象添加100個子對象,那麼我必須將父ID添加到每個子對象,並單獨保存每個子對象(100個單獨的POST/PUT請求),而I *可以*只是將所有100個ID添加到父項並完成一個POST/PUT並完成。 – KOGI 2013-03-06 16:17:23

2

我不能添加註釋ahmacleod的答案,但它是當場就只是我注意到,當孩子的記錄被修改父記錄不被標記爲髒。在問題的例子中,問題不會出現,因爲該名稱也在父記錄上進行了修改。

一般來說,如果你要遵循ahmacleod的第二個答案,你需要重寫RESTAdapter上的方法dirtyRecordsForHasManyChange。否則,序列化程序中的addHasMany永遠不會被調用,因爲記錄甚至沒有被標記爲髒。

現有的方法是這樣的:

dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) { 
    var embeddedType = get(this, 'serializer').embeddedType(record.constructor, relationship.secondRecordName); 

    if (embeddedType === 'always') { 
    relationship.childReference.parent = relationship.parentReference; 
    this._dirtyTree(dirtySet, record); 
    } 
}, 

所以我猜你會想是這樣的:

App.Store = DS.Store.extend({ 
    adapter: DS.RESTAdapter.extend({ 
    dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) { 
     relationship.childReference.parent = relationship.parentReference; 
     this._dirtyTree(dirtySet, record); 
    }, 

    serializer: DS.RESTSerializer.extend({ 
     addHasMany: function(hash, record, key, relationship) { 
     // custom ... 
     } 
    }) 
    }) 
}); 
+0

我沒有測試過這個,但它看起來很好。 – ahmacleod 2013-06-20 18:22:30