Создание вложенных моделей с помощью backboneJS + backbone-реляционного + requireJS - PullRequest
10 голосов
/ 01 апреля 2012

Я новичок в BackboneJS и застрял во вложенных отношениях, используя Backbone-реляционную модель с 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)

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

Ответы [ 4 ]

4 голосов
/ 09 мая 2012

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

http://jsfiddle.net/yNLbq

Как только объект достижим из текущей области видимости, все начинает работать:

http://jsfiddle.net/jDw5e

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

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

3 голосов
/ 09 июня 2013

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

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

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

Наконец, вам нужно разрешить циклическую ссылку. Доккаэби находится на правильном пути, когда он предлагает использовать 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 голосов
/ 19 апреля 2014

Я столкнулся с той же проблемой некоторое время назад и следовал подходу, который использовал Эндрю Ферк для своего вопроса: Реляционно-опорные подмодели с RequireJS . Проблема возникает из-за того, что вы определяете модели как модули Require, чтобы они не существовали в глобальной области видимости, где их могут искать магистральные реляционные. Вместо того, чтобы использовать глобальную область видимости (превосходит цель Require) или экспортировать (немного сложно с отношениями), вы можете определить область для ваших моделей и указать backbone-реляционному искать модели в ней, с помощью 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;
}

Кстати, вы должны изменить свою зависимость от Backbone и не требовать для нее jQuery и Underscore.

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

Вроде опоздал на это сейчас, но надеюсь, что это поможет другим.

2 голосов
/ 09 июня 2012

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

Если вам требуется специальное значение 'exports' в качестве зависимости в вашем вызове 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;
});
...