2013-03-28 110 views
2

我遇到以下問題。保存外鍵給其他具有多種關係的型號

在我的應用程序中,我有一個屏幕來創建一個新的Site。但是,當我通過控制器上的action保存新站點時,languages屬性不會隨POST-請求一起發送到服務器。

添加新網站的模板是這樣的:

<form class="form-horizontal"> 
<div class="control-group"> 
    <label class="control-label" for="name">Name</label> 
    <div class="controls"> 
     {{view Ember.TextField valueBinding="name"}} 
    </div> 
</div> 
<div class="control-group"> 
    <label class="control-label" for="languages">Languages</label> 
    <div class="controls"> 
     {{view Ember.Select contentBinding="controllers.languages" selectionBinding="languages" optionValuePath="content.id" optionLabelPath="content.description" multiple="true"}} 
      </div> 
</div> 
<div class="form-actions"> 
    <button {{ action "createSite" }} class="btn btn-primary">Save</button> 
</div> 

我定義我Store這樣的:

App.Store = DS.Store.extend({ 
    revision : 12, 
    adapter : DS.RESTAdapter.extend({ 
     namespace : 'rest' 
    }) 
}); 

這是我的控制器:

App.SitesNewController = Em.ObjectController.extend({ 
    needs: ['languages'], 
    name: null, 
    languages: null, 
    createSite : function() { 
     var self = this; 
     var name = this.get('name'); 
     var languages = this.get('languages'); 
     // Create the new Site model 
     var s = App.Site.createRecord({ 
      name : name 
     }); 
     $.each(languages,function(i,lang) { 
      s.get('languages').addObject(lang); 
     }); 

     this.get('store').commit(); 
    } 
}); 

這是Site -model

App.Site = DS.Model.extend({ 
    name : DS.attr('string'), 
    languages : DS.hasMany('App.Language') 
}); 

Language -model:

App.Language = DS.Model.extend({ 
    description : DS.attr('string') 
}); 

發送到我的服務器POST - 請求的數據是這樣的:

{ 
    "site":{"name":"test"} 
} 

所以我錯過了language - 屬性。其實我期望一個language_ids屬性與一個ID數組。

當我編輯RESTAdapter - 構型是這樣的:

DS.RESTAdapter.map('App.Site', { 
    languages: { embedded: 'always' } 
}); 

現在POST - 請求的數據是:

{ 
    "site": { 
    "name":"test", 
    "languages":[{ 
     "id":2,"description":"English" 
    },{ 
     "id":3,"description":"Deutsch" 
    }] 
    } 
} 

的語言都知道嵌入在請求數據。這是沒有問題的,在我保存之前,我在後端獲得了id。但知道它也期望language數據也嵌入到GET響應中。

在POST數據中發送id的方法是什麼?我希望它是這樣的:

{ 
    "site": { 
    "name":"test", 
    "languages":[2,3] 
    } 
} 

回答

6

這個答案主要來源於this other StackOverflow answer

App.Store = DS.Store.extend({ 
    revision : 12, 
    adapter : DS.RESTAdapter.extend({ 
     namespace : 'rest', 
     serializer: DS.RESTSerializer.extend({ 
      addHasMany: function (hash, record, key, relationship) { 
       var type = record.constructor, 
        name = relationship.key, 
        serializedHasMany = [], 
        manyArray, embeddedType; 

       embeddedType = this.embeddedType(type, name); 
       if (embeddedType !== 'always') { return; } 

       manyArray = record.get(name); 

       manyArray.forEach(function (record) { 
        serializedHasMany.push(record.get('id')); 
       }, this); 

       hash[this.singularize(key) + '_ids'] = serializedHasMany; 
      } 

     }) 

    }) 
}); 

僅供參考,您可以查看JSONSerializer,其中RESTSerializer主要來自繼承。可以找到addHasMany的代碼here

請注意,對於上面的代碼段,唯一真正不同的行是最後幾個。而不是序列化嵌入的記錄,ids被推到散列鍵下(如果它不是have its own check for embedded types,我會使用RESTSerializer#keyForHasMany

+1

非常感謝您的回答,我閱讀源代碼並完全獲取它。現在它工作正常。 –

+0

感謝殺手的回答。我省略了embeddedType!=='always'檢查,以便我可以同時獲得sideloading和多個hasMany id上傳 – cyberz

+0

PS。該代碼有一個小錯誤,它無法正確地將camelcase屬性映射到REST約定(例如,childNodes變成childNode_ids而不是child_node_ids)。解決方法是在序列化程序對象的末尾修改以下內容:key = this.keyForAttributeName(type,name); hash [this.singularize(key)+'_ids'] = serializedHasMany; – cyberz

相關問題