1
votes

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?

1
This is something that has frustrated me too, in fact it's a problem in core Backbone, as many collection function calls will return an array of models instead of another collection object, which would allow chaining and avoid verbosity. What you are looking for can be achieved with github.com/mikeapr4/Backbone.hierarchy or github.com/blittle/backbone-nested-modelsmikeapr4
@mikeapr4 - it works with the traditional relational backbone, he was missing the reverseRelation which tie the sub-models back to the Model. Check the answer below. There is a working example on the documentation too => backbonerelational.org/#examplesWinter Soldier

1 Answers

1
votes
  • 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>