Search code examples
requirejsbackbone-relational

Backbone-relational submodels with RequireJS


I'm trying to find a way to use Backbone-relational submodels with RequireJS, where the submodels are in different files than the supermodel.

For example:

// app.js
define(function() {
  var app = {};
  var app.ns = {};
  Backbone.Relational.store.addModelScope(app.ns);
});

// Classroom/Person.js
define(["app", "./Student", "./Professor"], function(app) {
  app.ns.Classroom.Person = Backbone.RelationalModel.extend({
    subModelTypes: {
      'Student': 'Classroom.Student'
      'Professor': 'Classroom.Professor'
    },

    alertHello: function() {}
  });

  return app.ns.Classroom.Person;
});

// Classroom/Student.js
define(["require", "app", "./Person"], function(require, app) {
  app.ns.Classroom.Student = require("./Person").extend({
    alertHello: function() {
      alert("Hello, I am student " + this.get("name"));
    }
  });

  return app.ns.Classroom.Student;
});

// Classroom/PersonCollection.js
define(["app", "./Person"], function (app, Person) {
  app.ns.Classroom.PersonCollection = Backbone.Collection.extend({
    model: Person
  });
});

// alertPeople.js
define(["Classroom/PersonCollection"], function(PersonCollection) {
  var people = PersonCollection([{"name": "Bob", "type": "Person"}]);
  people.each(function(person) {
    person.alertHello();
  });
});

When I execute alertPeople.js, I expect an alert of "Hello, I am student Bob", but instead I get this error: Uncaught Error: Module name "Classroom/Person" has not been loaded yet for context: _ due to my circular dependency. What's a possible solution getting around this?

My next issue may potentially be with the scope of of Backbone-relational. In my app.js file I add app.ns part of the of scope, and I make sure all of my models are defined in the app.ns object. I do this so when I define my subModelTypes, it can actually reference the submodels, but I'm not sure if this will work yet, as I cannot get past the circular dependency issue.

Any help is greatly appreciated. Thank you!


Solution

  • I ended up solving the problem, and I hope this helps others in the future.

    First, I modified my code to the following:

    // app.js
    define(function() {
      var app = {};
      var app.ns = {};
      Backbone.Relational.store.addModelScope(app.ns);
    });
    
    // Classroom/Person.js
    define(["app"], function(app) {
      app.ns.Classroom.Person = Backbone.RelationalModel.extend({
        subModelTypes: {
          'Student': 'Classroom.Student'
          'Professor': 'Classroom.Professor'
        },
    
        alertHello: function() {}
      });
    
      return app.ns.Classroom.Person;
    });
    
    // Classroom/Student.js
    define(["app", "./Person"], function(app, Person) {
      app.ns.Classroom.Student = Person.extend({
        alertHello: function() {
          alert("Hello, I am student " + this.get("name"));
        }
      });
    
      return app.ns.Classroom.Student;
    });
    
    // Classroom/PersonCollection.js
    define(["app", "./Person", "./Student", "./Professor"], function (app, Person) {
      app.ns.Classroom.PersonCollection = Backbone.Collection.extend({
        model: Person
      });
    });
    
    // alertPeople.js
    define(["Classroom/PersonCollection"], function(PersonCollection) {
      var people = PersonCollection([{"name": "Bob", "type": "Person"}]);
      people.each(function(person) {
        person.alertHello();
      });
    });
    

    My changes included removing Student and Professor dependencies in the Classroom/Person.js file and moved them into the Classroom/PersonCollection.js file.

    After this, I ran into a bug with Backbone-relational where addModelScope had a bug with submodels and namespaces, but I fixed it and made a pull request: https://github.com/PaulUithol/Backbone-relational/pull/211, which has been accepted.

    A more complete example can be found at https://github.com/andrewferk/backbone-relational-submodels.