2013-12-21 77 views
12

我需要一次將所有深層對象保存到服務器,並且無法在線查找任何使用最新的支持數據(1.0.0-beta.4)的示例。Ember數據:保存關係

例如,有這些模特: (jsfiddle

App.Child = DS.Model.extend({ 
    name: DS.attr('string'), 
    age: DS.attr('number'), 
    toys: DS.hasMany('toy', {async:true, embedded:'always'}), 
}); 
App.Toy = DS.Model.extend({ 
    name: DS.attr('string'), 
    child: DS.belongsTo('child') 
}); 

而這種代碼:

actions: { 
    save: function(){ 
     var store = this.get('store'), 
      child, toy; 

     child = store.createRecord('child', { 
      name: 'Herbert' 
     }); 
     toy = store.createRecord('toy', { 
      name: 'Kazoo' 
     }); 

     child.set('toys', [toy]); 
     child.save(); 
    } 
} 

它不僅節省了JSON的子對象,但沒有任何的玩具 - 沒有側裝:

{ 
    child: { 
    age: null 
    name: "Herbert" 
    } 
} 

我是否必須手動保存玩具t OO?反正是有,我可以把它發送下面的JSON到服務器:

{ 
    child: { 
    age: null 
    name: "Herbert", 
    toys: [{ 
     name: "Kazoo" 
    }] 
    } 
} 

或者

{ 
    child: { 
    age: null 
    name: "Herbert", 
    toys: [1] 
    } 
} 

見的jsfiddle:http://jsfiddle.net/jgillick/LNXyp/2/

回答

0

我需要一個深刻的對象,而不是側裝一個,因此基於kingpin2k的答案,我想出了這個:

現在
DS.JSONSerializer.reopen({ 
    serializeHasMany: function(record, json, relationship) { 
     var key = relationship.key, 
      property = Ember.get(record, key), 
      relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship); 

     if (property && relationshipType === 'manyToNone' || relationshipType === 'manyToMany' || 
      relationshipType === 'manyToOne') { 

      // Add each serialized nested object 
      json[key] = []; 
      property.forEach(function(item, index){ 
       json[key].push(item.serialize()); 
      }); 
     } 
    } 
}); 

當你調用child.serialize(),它將返回這個對象:

{ 
    child: { 
    name: "Herbert", 
    toys: [ 
     { 
     name: 'Kazoo' 
     } 
    ] 
    } 
} 

這是我需要的。這裏是jsfiddle它的行動:http://jsfiddle.net/jgillick/LNXyp/8/

+0

使用Ember 1.3.1/data 1.0.0-beta 6,'property = Ember.get(record,key)'似乎返回一個空的promise數組。這特別奇怪,因爲我可以用'record.get('key')。然後(函數(items){...})'訪問子記錄'。任何想法,如果這是一個已知的問題? – eriknelson

3

玩具不能同時異步和始終嵌入,那些是相互矛盾的選擇。嵌入式僅存在於當前活動模型序列化器中。

toys: DS.hasMany('toy', {embedded:'always'}) 

玩具是多對一的關係,因爲在屬於關聯方存在的關係會更有效玩具的保存過程中保存的關係。這就是說,如果你一次創建它,那麼就想把它保存在一個大塊中,這是壓倒一切的地方。

serializeHasMany: function(record, json, relationship) { 
    var key = relationship.key; 

    var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship); 

    if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany' || 
     relationshipType === 'manyToOne') { 
    json[key] = get(record, key).mapBy('id'); 
    // TODO support for polymorphic manyToNone and manyToMany relationships 
    } 
}, 

和你保存應該是這樣的

var store = this.get('store'), 
     child, toy; 

    child = store.createRecord('child', { 
     name: 'Herbert' 
    }); 
    toy = store.createRecord('toy', { 
     name: 'Kazoo' 
    }); 

    child.get('toys').pushObject(toy); 
    child.save().then(function(){ 
     toy.save(); 
    }, 
    function(err){ 
     alert('error', err); 
    }); 
+0

「玩具」在哪裏定義?如果你的意思是'child.get('toys')。save()',或者訪問promise的響應,那麼這個調用是否保存在每一行上獨立的模型或一次性保存它們? 我和Jeremy有同樣的問題,當我嘗試調試/檢查hasMany屬性時,就像在這種情況下查看child.get('toys'),即使在我推送新記錄之後,數組中的值爲空。我認爲這是因爲Ember-Data知道將玩具的ID存儲在玩具數組中,但玩具沒有ID,因爲它沒有被保存。 –

+0

是的,那應該是'玩具',我是保存個人玩具。 – Kingpin2k

+0

所以,如果我正確理解這一點。我們已經建立了模型與一對多的關係,孩子有許多玩具,玩具屬於孩子。在內部,玩具模型上會有一個'childId'屬性,這個屬性實際上會被持久化。 當您調用'child.pushObject(玩具)'時,兩者之間的關係建立並且一旦孩子被保存,玩具的childId屬性會自動更新? 我期待着你必須在promise履行處理函數裏面調用'toy.set('child',response)'。 –

8

這裏的答案是過時的。 Ember Data現在支持嵌入式記錄,它允許您完成您想要做的事情,即在一個大的有效負載中獲取併發送完整的對象圖。例如,如果你的模型設置如下:

App.Child = DS.Model.extend({ 
    name: DS.attr('string'), 
    age: DS.attr('number'), 
    toys: DS.hasMany('toy') 
}); 
App.Toy = DS.Model.extend({ 
    name: DS.attr('string'), 
    child: DS.belongsTo('child') 
}); 

您可以定義自定義序列爲您的孩子型號:

App.ChildSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { 
    attrs: { 
    toys: {embedded: 'always'} 
    } 
}); 

這告訴灰燼數據,你想「玩具」到作爲'孩子'有效載荷的一部分被包括在內。從您的API的HTTP GET響應應該是這樣的:

{ 
    "child": { 
    "id": 1, 
    "name": "Todd Smith", 
    "age": 5, 
    "toys": [ 
     {"id": 1, "name": "boat"}, 
     {"id": 2, "name": "truck"} 
    ] 
    } 
} 

當你保存你的模型,子玉的數據將發送該服務器:

{ 
    "child":{ 
     "name":"Todd Smith", 
     "age":5, 
     "toys":[ 
     { 
      "id":"1", 
      "name":"boat", 
      "child":"1" 
     }, 
     { 
      "id":"2", 
      "name":"truck", 
      "child":"1" 
     } 
     ] 
    } 
} 

這裏是一個JSBin演示這一點。

http://emberjs.jsbin.com/cufaxe/3/edit?html,js,output

在JSbin,當您單擊「保存」按鈕,你就需要使用開發檢查,以查看在發送到服務器的請求。

+0

你知道這是否是首選的方法嗎?我的理解是,在GET響應中包含嵌入式記錄並不總是最有效的。但是,我可以看到嵌入記錄在POST/PUT請求中的好處。 – antony

+1

@antony,你在問一個API設計問題,它不是專門關於Ember Data的。如果您認爲彙總(例如訂單有訂單項目,但訂單項目本身沒有標識),則您需要使用嵌入式記錄。此外,如果您需要在一個原子事務中發生更新(例如再次訂購和訂購商品),那麼您將需要使用嵌入式記錄。但是,如果每個模型都有自己可識別的端點,那麼嵌入式記錄就沒有意義。 –