我已经看过文档好几次了,但这方面我仍然不清楚。完全有可能我认为主干关系做了一些它没有做的事情。
我正在寻找一种方法来定义基于键的关系,以避免所有的样板文件抓取废话。
以典型的艺术家和专辑为例:一个艺术家有许多专辑,由album.artist_id
定义/api/artist/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?它一定只是键/键源/键目的地的一些排列,我还没有尝试,或者是一个问题,骨干关系没有试图解决,但我的文档搜索失败了,我认为一个简洁的答案可能会帮助未来的谷歌人。
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
所以,@xzhang的方法让我在这个问题上不断迭代。首先,我很想证明自己是错的,但我还没有找到一种方法,可以在不添加自定义代码的情况下,通过主干关系处理这个问题。因为在我看来,这是一个非常基本的一对多关系的例子,我仍然抱着希望,我只是没有得到一些明显的东西。
这是我最后处理这种情况的方法。不幸的是,当someobject.fetch(' somerrelationship ')被调用时,它仍然不会自动从服务器获取,这是我真正想要的。解析函数对于大多数人来说是不必要的,但是对于我正在调用的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,...]}
在第一次调用。get('children')时扩展autoFetch子对象正好可以,但我还没有发现如何在不修改主干关系本身的情况下做到这一点。
我正面临着确切的问题(骨干关系有许多最佳实践),经过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将创建一个url: /api/album/?artist=62351
的集合。然后您只需要获取集合:artist.get('albums').fetch()
。
希望能有所帮助,我还在寻找更好的解决方案。