2012-04-01 6 views
10

Я новичок в BackboneJS, и я застрял с вложенными отношениями с использованием Backbone-реляционной модели с RequireJS -I думаю, что я столкнулся с круговыми проблемами. Любая помощь будет высоко оценена!Создание вложенных моделей с backboneJS + backbone-relational + requireJS

У меня есть следующие модели и коллекции:

/* 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; 
}); 

Когда я инициализировать объект ModuleModel, он выдает следующее сообщение об ошибке:

Relation=child; no model, key or relatedModel (function(){ parent.apply(this, arguments); }, "children", undefined) 

Не могли бы вы мне точку в правильном направлении?

+0

Как и http://stackoverflow.com/questions/9225640/how-to-represent-uml-relations-with-backbone-relational –

ответ

4

Это выглядит как проблема. Во время инициализации ModuleModel он хочет создать hasMany отношения с самим собой, но он не может найти себя, и это даст вам горе в виде указанной ошибки:

http://jsfiddle.net/yNLbq

После того, как объект достижим от тока Scope вещи начинают работать:

http://jsfiddle.net/jDw5e

возможным решением было бы дать модели и коллекции пространства имен для себя, которое может быть достигнуто из текущей области.

Надеюсь, это поможет.

2

Из комментария в магистральном-relational.js v0.5.0 (строка 375):
// «экспорт» должен быть глобальным объектом, где «relatedModel» можно найти на если дан в виде строки.

Если вам требуется специальное значение «export» в качестве зависимости в вашем вызове define, а затем поместите ваш модуль на объект экспорта до его возвращения, вы можете ссылаться на этот модуль как на строку или как на членство в экспорте.

в ModuleModel.js:

define(['exports', 'use!backbone', 'use!backbone-relational'], function(exports, Backbone) { 
    var ModuleModel = Backbone.RelationalModel.extend({ 
    relations: [ 
     { 
     type: Backbone.HasMany, 
     key: 'groups', 
     relatedModel: 'ModuleModel', 
     collectionType: 'ModuleCollection' 
     } 
    ] 
    }); 
    exports.ModuleModel = ModuleModel; 
    return ModuleModel; 
}); 

и ModuleCollection.js:

define(['exports', 'use!backbone'], function(exports, Backbone) { 
    var ModuleCollection = Backbone.RelationalModel.extend({ 
    url: '/api/v1/module/'; 
    model: exports.ModuleModel; 
    }); 
    exports.ModuleCollection = ModuleCollection; 
    return ModuleCollection; 
}); 
+3

Экспорт - это не то, что вы определяете; он обрабатывается специально по требованию. Requirejs создает словарь и передает его любым определениям, которые требуют «экспорта», чтобы вы могли делиться значениями между вызовами определения. Вам не нужно создавать файл и не делать ничего особенного - просто используйте магическое имя «export» как одну из ваших зависимостей. – dokkaebi

+0

Можете ли вы сказать мне, какой модуль мне следует создать? оба или только один, и если только один, который между ModuleCollection и ModuleModel? –

+0

Используя код, который я опубликовал, модули ModuleModel и ModuleCollection должны работать должным образом. В другом месте вашего кода вы можете сделать что-то вроде 'require (['ModuleCollection', 'ModuleModel'], function (ModuleCollection, ModuleModel) {myModules = new ModuleCollection(); myModel = new ModuleModel ({/ * some values ​​* /}); myModules.add (myModel);} '. Это может помочь вам понять, что вы пытаетесь сделать - если это не работает должным образом, вы можете открыть здесь новый вопрос и ссылку на него. – dokkaebi

3

Я наткнулся на эту проблему здесь: RequireJS + BackboneRelational + Self-Referential. Кажется, он унаследовал некоторые из своих проблем из этой темы, поэтому я подумал, что могу добавить свой копейки.

Во-первых, поскольку вы используете RequireJS, глобальных переменных нет. Вы не можете просто указать название объекта, вам нужно указать фактические ссылки на объекты для relatedModel и collectionType.

Ваш хитрая проблема в том, что ModuleModel «s relatedModel фактически ModuleModel сам, который не будет определен, когда вы назначаете его relatedModel (с использованием модели AMD). Вы должны отложить назначение до тех пор, пока не будет назначен ModuleModel.

Наконец, вам необходимо решить круглую ссылку. dokkaebi находится на правильном пути, когда он предлагает использовать exports, но его реализация фактически злоупотребляет exports.При экспорте прикрепите объект непосредственно к exports, как он предлагает, но при импорте вам нужно обратиться к модулю, чтобы использовать его, а не exports.

Это должно работать:

ModuleModel.js

define(['exports', 'ModuleCollection'], function (exports, Module) { 
    'use strict'; 

    var ModuleModel = Backbone.RelationalModel.extend({ 
     urlRoot: 'api/module', 
     _radius: 50, 
     relations: [{ 
      type: Backbone.HasMany, 
      key: 'children', 
      // ModuleModel is undefined; this line is useless 
      // relatedModel: ModuleModel, 
      // no globals in require; must use imported obj ref 
      collectionType: Module.Collection, 
      reverseRelation: { 
       key: 'parent_id', 
       includeInJSON: 'id' 
      } 
     }], 
     url: function() { 
      return this.id? 'api/module/' + this.id : 'api/module'; 
     } 
    }); 

    // Now that `ModuleModel` is defined, we can supply a valid object reference: 
    ModuleModel.prototype.relations[0].relatedModel = ModuleModel; 

    // Attach `Model` to `exports` so an obj ref can be obtained elsewhere 
    exports.Model = ModuleModel; 
}); 

ModuleCollection.js

define(['exports', 'ModuleModel'], function(exports, Module) { 
    'use strict'; 

    var ModuleCollection = Backbone.Collection.extend({ 
     // must reference the imported Model 
     model: Module.Model, 
     url: 'data.php' // <-- or wherever 
    }); 

    // Attach `Collection` to `exports` so an obj ref can be obtained elsewhere 
    exports.Collection = ModuleCollection; 
}); 

Main.js

define(['ModuleCollection'], function(Module) { 
    'use strict'; 

    var modules = new Module.Collection(); 
    modules.fetch().done(function() { 
     modules.each(function(model) { 
     console.log(model); 
     }); 
    }); 

}); 
2

Я столкнулся с той же проблемой некоторое время назад и следовал подходу, использованному Эндрю Ферком для его вопроса: Backbone-relational submodels with RequireJS. Проблема возникает из-за того, что вы определяете модели как требуемые модули, чтобы они не существовали в глобальной области, где базовая реляционная система может их искать. Вместо того, чтобы использовать глобальную область действия (превосходит цель Требовать) или экспортировать (бит сложный с отношениями), вы можете определить область для своих моделей и указать базовую связь для поиска моделей в ней с помощью addModelScope().

//modelStore.js - A scope in which backbone-relational will search for models 
//Defined separately so you can access 'modelStore' directly for your models instead of requiring 'app' every time. 
define(['app'], function(app) { 
    app.modelStore = {}; 
    Backbone.Relational.store.addModelScope(app.modelStore); 
    return app.modelStore; 
} 

Кстати, вы должны Shim позвоночник зависимость и не нужно требовать JQuery и подчерк для него.

//ModuleModel (The ModuleModel module. Nice.) 
define(['modelStore', 'backbone', 'backboneRelational'], function(modelStore, Backbone { 
    modelStore.ModuleModel = Backbone.RelationalModel.extend({ 
     relations: [ 
     { 
      type: Backbone.HasMany, 
      key: 'groups', 
      relatedModel: 'ModuleModel', //Not modelStore.ModuleModel 
      collectionType: 'ModuleCollection' 
     } 
     ] 
    }); 
    return modelStore.ModuleModel; 
}); 

Доброго времени для этого сейчас, но надеюсь, что это поможет другим.