我已经多次访问过这些文档,但这方面仍然不清楚。完全有可能我认为骨干关系会做一些它没有做到的事情。
我正在寻找基于键定义关系的方法,以避免所有样板文件取出废话。
以规范的艺术家和专辑为例: 艺术家有很多专辑,由album.artist_id
定义/ api / artist / 62351可能会返回
{
id: 62351,
name:"Jimi Hendrix"
}
同样/ api / album?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失败了,我想对此有一个简明的答案。这可能有助于未来的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'
});
Bonus指向一个示例模型,该模型使用parent_id
引用其自相邻列表样式答案 0 :(得分: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()帮助器分配给setOptions。
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')时自动提取子项的扩展只是票证,但我还没有发现如何在不修改骨干关系本身的情况下这样做。
答案 1 :(得分: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将使用url创建一个集合:/api/album/?artist=62351
。
然后你只需要获取集合:artist.get('albums').fetch()
。
希望这可以提供帮助,我仍在寻找更好的解决方案。