I am new to BackboneJS and I am stuck with nested relations using Backbone-relational Model with RequireJS -I think I runned into circular issues. Any help will be highly appreciated!
I have the following model and collection:
/* Module Model at models/module*/
define([
'jquery',
'underscore',
'backbone',
'backboneRelational',
], function($, _, Backbone) {
var ModuleModel = Backbone.RelationalModel.extend({
urlRoot: 'api/module',
_radius: 50,
relations: [{
type: Backbone.HasMany,
key: 'children',
relatedModel: 'ModuleModel',
collectionType: 'ModuleCollection',
reverseRelation: {
key: 'parent_id',
includeInJSON: 'id'
}
}],
url: function() {
return this.id? 'api/module/' + this.id : 'api/module';
}
});
return ModuleModel;
});
/* Module Collection */
define([
'jquery',
'underscore',
'backbone',
'models/module'
], function($, _, Backbone, ModuleModel) {
var ModuleCollection = Backbone.Collection.extend({
model: ModuleModel,
url: 'api/modules'
});
return ModuleCollection;
});
When I initialize the object ModuleModel, it throws the following error:
Relation=child; no model, key or relatedModel (function (){ parent.apply(this, arguments); }, "children", undefined)
Could you point me to the right direction?
I came across this problem from here: RequireJS + BackboneRelational + Self-Referential. He seems to have inherited some of his problems from this thread so I thought I might add my dime.
First, since you're using RequireJS, there are no global variables. You can't simply supply the name of the object, you need to supply actual object references for
relatedModel
andcollectionType
.Your trickiest issue is that
ModuleModel
'srelatedModel
is actuallyModuleModel
itself, which won't be defined when you assign it torelatedModel
(using the AMD model). You have to defer assignment until afterModuleModel
is assigned.Finally, you need to resolve the circular reference. dokkaebi is on the right track when he suggests using
exports
, but his implementation actually misusesexports
. When exporting, attach the object directly toexports
as he suggests, but when you import it you need to reference the module to use it, notexports
.This should work:
ModuleModel.js
ModuleCollection.js
Main.js
This looks like a scoping issue. During initialization of
ModuleModel
it wants to create ahasMany
relation with itself, but it can't find itself and it will give you grief in form of said error:http://jsfiddle.net/yNLbq
Once the object is reachable from the current scope things start to work out:
http://jsfiddle.net/jDw5e
A possible solution would be to give models and collection a namespace for themselves which can be reached from the current scope.
Hope this helps.
I ran into the same problem a while back and followed the approach used by Andrew Ferk for his question: Backbone-relational submodels with RequireJS. The problem arises because you're defining models as Require modules so they don't exist on the global scope, where backbone-relational can look for them. Instead of using global scope (beats the purpose of Require) or exports (bit tricky with the relations), you can define a scope for your models and tell backbone-relational to look for models in it, with addModelScope().
By the way you should shim your Backbone dependency and not need to require jQuery and Underscore for it.
Kinda late for this now but hope it helps others.
From a comment in backbone-relational.js v0.5.0 (line 375):
// 'exports' should be the global object where 'relatedModel' can be found on if given as a string.
If you require the special 'exports' value as a dependency in your define call, and then place your module onto the exports object before you return, then you can reference that module as a string or as a member of exports.
in ModuleModel.js:
and in ModuleCollection.js: