Search code examples
javascriptbackbone.jsbackbone-relational

Backbone Relational - Deep nested models/collections


Having some fun with Backbone-relational.js v0.10.0

I have a JSON object which contains nested models and collections, to keep this simple I have made the example below. A company can have many employees, employees can have one address and many tasks.

{
    name: 'Nicks Company',
    employees: [{
        name: 'Bob',
        address: {
            line1: '1 City Lane',
            city: 'London'
        },
        tasks: [{
            description: 'Make this work'
        }]
    }, {
        name: 'Bill',
        address: {
            line1: '1 The Street',
            city: 'Birmingham'
        },
        tasks: [{
            description: 'Make a cake'
        }, {
            description: 'Fix all the things'
        }]
    }]
}

In the below JSFiddle (console) you can see that the address is a plain object, also the commented out code for tasks has been disabled as tasks is returned as an array.

JSFiddle: https://jsfiddle.net/nwa29uLv/2/

Neither the address model or the collection of tasks are created as Backbone instances, is this possible or am I pushing the limits of this plugin?


Solution

    • Here is how I resolved the issue. You were missing the reverseRelation.
    • BTW did you look at this post? It has a similar issue.

    Follow the fiddle here

    var Address = Backbone.RelationalModel.extend({});
    
    var Task = Backbone.RelationalModel.extend({});
    var TaskCollection = Backbone.Collection.extend({
      model: Task
    });
    
    var Employee = Backbone.RelationalModel.extend({
      relations: [{
        type: Backbone.HasOne,
        key: 'address',
        relatedModel: Address,
        reverseRelation: {
          type: Backbone.HasOne,
          key: 'employee'
        }
      }, {
        type: Backbone.HasMany,
        key: 'tasks',
        collectionType: TaskCollection,
        relatedModel: Task,
        reverseRelation: {
          type: Backbone.HasOne,
          key: 'operatesOn'
        }
      }]
    });
    
    var EmployeeCollection = Backbone.Collection.extend({
      model: Employee
    });
    
    var Company = Backbone.RelationalModel.extend({
      relations: [{
        type: Backbone.HasMany,
        key: 'employees',
        relatedModel: Employee,
        reverseRelation: {
          key: 'worksFor'
        }
      }]
    });
    
    var company = new Company({
      name: 'Nicks Company',
      employees: [{
        name: 'Bob',
        address: {
          line1: '1 City Lane',
          city: 'London'
        },
        tasks: [{
          description: 'Make this work'
        }]
      }, {
        name: 'Bill',
        address: {
          line1: '1 The Street',
          city: 'Birmingham'
        },
        tasks: [{
          description: 'Make a cake'
        }, {
          description: 'Fix all the things'
        }]
      }]
    });
    
    console.log('Company:', company.get('name'));
    company.get('employees').each(function(employee) {
      console.log('Employee:', employee.get('name'));
      console.log('Employee:', employee.get('name'), 'Address Model:', employee.get('address').get('city'));
      employee.get('tasks').each(function(task) {
        console.log('Employee:', employee.get('name'), 'Task: ', task.get('description'));
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone-relational/0.10.0/backbone-relational.js"></script>