2013-04-12 42 views
3

我已經在文檔中進行過很多次了,但這方面仍然不清楚。我認爲骨幹關係完全可以做一些它沒有的事情。基於密鑰的骨幹關係關係定義的正確方法

我正在尋找方式來定義基於關鍵的關係,以避免所有的樣板取材無稽之談。

採取規範的藝術家和專輯?例如: 一個藝術家有許多專輯由album.artist_id定義

/API /藝術家/ 62351可能返回

{ 
    id: 62351, 
    name:"Jimi Hendrix" 
} 

類似/ API /專輯artist_id = 62351可能返回

[ 
{ 
    id:5678, 
    name: "Are You Experienced?" 
    artist_id: 62351 
}, 
{ 
    id: 4321, 
    name: "Axis: Bold as love", 
    artist_id: 62351 
} 
] 

我怎麼可能定義藝術家和專輯的關係,使得

var hendrixInstance = new Artist({id:62351}); 
hendrixInstance.get('albums'); 

將根據專輯foreign_key artist_id獲取並返回一個專輯集合?它必須是我還沒有嘗試的key/keySource/keyDestination的一些排列,或者是一個骨幹關係沒有試圖解決的問題,但是我的doc groking失敗了,我想這個簡潔的回答SO可能會幫助未來的Google員工。

var Artist = Backbone.RelationalModel.extend({ 
    urlRoot: '/api/artist', 
    relations:[{ 
    key: 'albums', //Docs say this is the foreign key name, but in practice it doesn't appear that way. Need keySource/Destination? 
    type: Backbone.HasMany, 
    reverseRelation: { 
     key: 'artist', 
     type: Backbone.HasOne 
    } 
    }] 
}); 
var Album = Backbone.RelationalModel.extend({ 
    urlRoot: '/api/album' 
}); 

獎勵積分,引用其自身鄰接表風格PARENT_ID

回答

0

我對着正好問題(Backbone-relational hasmany best practices)後2天的研究和考慮的源代碼示例模型,我不不要以爲key/keySource/keyDestination會做這項工作(如果我錯了,請糾正我)。

所以我最終創建了我自己的關係類型,到目前爲止工作正常。這可能不是一個好的解決方案,但希望可以幫助你。

var LazyMany = Backbone.HasMany.extend({ 
    setRelated: function (related) { 
    var relation = this.options 
     , instance = this.instance 
    ; 

    if (related && !_.result(related, 'url')) { 
     related.url = relation.relatedModel.prototype.urlRoot + 
     '?' + relation.reverseRelation.key + '=' + instance.id; 
    } 
    return LazyMany.__super__.setRelated.apply(this, arguments); 
    } 
}); 

然後在你的模型:

var Album = Backbone.RelationalModel.extend({ 
    urlRoot: '/api/album/' 
}); 

var Artist = Backbone.RelationalModel.extend({ 
    urlRoot: '/api/artist/', 
    relations:[{ 
    key: 'albums', 
    type: LazyMany, 
    includeInJSON: false, 
    relatedModel: Album, 
    reverseRelation: { 
     key: 'artist', 
     // I didn't test this, I don't have artist_id, artist is "id" in my app 
    keySource: 'artist_id', 
    keyDestination: 'artist_id', 
     includeInJSON: 'id' 
    } 
    }] 
}); 

所以,如果你沒有定義collectionType或您的收藏沒有URL字段中,LazyMany將創建一個收集與網址:/api/album/?artist=62351。 然後你只需要取回集合:artist.get('albums').fetch()

希望這可以幫助,我仍然在尋找更好的解決方案。

+0

謝謝@xzhang,我很高興地看到,我不是唯一一個誰預期出來的東西骨幹關係的不同。我試過你的方法,它確實有效,但經過幾次額外的迭代,我最終使用了一個變體。 – nebulous

3

所以,@ xzhang的方法讓我反覆討論這個問題。首先,我很想在這方面被證明是錯誤的,但是我還沒有找到一種方法,即骨幹關係無需額外的自定義代碼即可處理此問題。由於在我看來這是OneToMany關係的一個令人難以置信的基本例子,我仍然抱着希望,我只是沒有明顯的東西。

下面是我最終做的處理情況。不幸的是,當someobject.fetch('somerelationship')被調用時,它仍然不會自動從服務器獲取,這正是我真正想要的。對於大多數人來說,解析函數不是必需的,但它是我打電話給api所必需的。

首先,我建立了從基本集合擴展:

var BaseCollection = Backbone.Collection.extend({ 
    initialize: function(models, options) { 
     if (_.isObject(options.relation)) { 
     this.url = '/api/' 
     + options.relation.keySource 
     + '?search.'+options.relation.reverseRelation.keySource 
     + '=' + options.foreignId; 
     } 
    }, 
    parse: function(res) { return res.success ? res.list : res }, 
    }); 

然後,可重複使用的輔助功能(也許可以捲成BaseCollection),以幫助創建關係

function collectionOptions(instance) { 
    return {"relation":this, "foreignId":instance.get('id') }; 
    }; 

最後,那些關係被告知使用BaseCollection作爲它們的CollectionType,並且collectionOptions()幫助器被分配來設置collectionOptions。

var Form = BaseModel.extend({ 
    urlRoot: '/api/form', 
    relations:[ 
     { 
     key: 'fills', 
     keySource: 'fill', 
     relatedModel: Fill, 
     type: Backbone.HasMany, 
     collectionOptions: collectionOptions, 
     collectionType: BaseCollection, 
     reverseRelation: { 
      key: 'form', 
      keySource: 'form_id', 
      type: Backbone.HasOne 
     } 
     },{ 
     key: 'children', 
     keySource: 'form', 
     relatedModel: 'Form', 
     type: Backbone.HasMany, 
     collectionOptions: collectionOptions, 
     collectionType: BaseCollection, 
     reverseRelation: { 
      key: 'parent', 
      keySource: 'parent_id', 
      type: Backbone.HasOne 
     } 
     } 
    ] 
    }); 

這使我避免改變服務器端API返回ID的列表,然後逐個獲取這些ID。相反,我可以只:

var form = new Form({id:1}); 
form.get('children').fetch(); 
form.toJSON(); //now has {id:1, ..., ..., children:[child,child,child,...]} 

到自動提取孩子的擴展在第一次調用來獲得(「孩子」)將只是門票,但我還沒有發現如何做到這一點,而無需修改骨幹關係本身。