Skip to content

Instantly share code, notes, and snippets.

@jdkanani
Last active December 18, 2015 17:59
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdkanani/5822296 to your computer and use it in GitHub Desktop.
Save jdkanani/5822296 to your computer and use it in GitHub Desktop.
This example demonstrates how to incrementally load and save object graphs using Backbone-associations. This is important because rarely, there would be a need to fetch (or save) a entire object hierarchy from the server.
var MyApp = {
context: {}
};
MyApp.context.departments = null;
MyApp.context.employees = null;
var counter = 100;
/**
* Initialization of associated models
*/
var Location = Backbone.AssociatedModel.extend({
defaults:{
id:-1,
add1:"",
add2:null,
zip:"",
state:""
},
urlRoot: '/location'
});
var Locations = Backbone.Collection.extend({
model: Location,
url: function() {
return '/locations';
}
});
var Department = Backbone.AssociatedModel.extend({
initialize: function(){
var dept = this;
this.get('locations').url = function(){
return '/department/' + dept.id + '/locations';
}
},
relations:[
{
type:Backbone.Many,
key:'locations',
collectionType: Locations
}
],
defaults:{
name:'',
number:-1
},
urlRoot: '/department'
});
var Departments = Backbone.Collection.extend({
model: Department,
comparator: function(d){
return d.get('number');
},
url: '/departments',
sync: function(method, collection, options) {
return options.success.call(this, [
{id:1, name:"sales", number: 21, locations:[{id:'l1', zip: 94404}]},
{id:2, name:"admin", number: 22, locations:[{id:'l2', zip: 94404}]}
], options);
}
});
// toDepartment - which returns department model object using passed id
var toDepartment = function(id) {
if (id instanceof Department) return id;
if (_.isObject(id)) return id;
var deps = MyApp.context.departments;
var found = deps && deps.find(function (m) {
return m.get(m.idAttribute) === id;
});
return found ? found : id;
}
var Employee = Backbone.AssociatedModel.extend({
relations:[
{
type:Backbone.One,
key:'works_for',
relatedModel: Department,
// property to map work_for to department object
// using `idAttribute`
map: toDepartment
}
],
defaults: {
sex:'M', //{F,M}
fname:"",
lname:""
},
getName: function() {
return this.get('fname') + " " + this.get('lname');
},
urlRoot: '/employee',
toJSON: function(){
var department = this.get('works_for');
return {
fname: this.get('fname'),
lname: this.get('lname'),
sex: this.get('sex'),
age: this.get('age'),
works_for: department && department.get(department.idAttribute)
};
},
// For demo purposes only
sync: function(method, model, options){
var response = {};
if (method === 'create') {
response[model.idAttribute] = counter++; // dummy id
} else if(method === 'update'){
// Let's assume that - after success update, server sends model's json object
response = model.toJSON();
}
return options.success.call(this, response);
}
});
var Employees = Backbone.Collection.extend({
model: Employee,
url: '/employees',
comparator: function(e){
return e.get('lname');
},
sync: function(method, c, options) {
return options.success.call(this, [
{id: 1, fname:"John", lname:"Doe", works_for: 1},
{id: 2, fname:"Clark", lname:"Kent", works_for: 2}
]);
}
});
/**
* Fetch
*/
// Create department list
var departments = MyApp.context.departments = new Departments();
// Fetch `MyApp.context.departments`
departments.fetch();
console.log("MyApp.context.departments : ");
console.log(departments);
// Create employee list
var employees = MyApp.context.employees = new Employees();
employees.on("add", function(newModel, col, options){
console.log("New joinee : '" + newModel.getName() + "'(id: "+ newModel.get('id') +")");
});
// Fetch `MyApp.context.employees`
employees.fetch();
console.log("MyApp.context.employees : ");
console.log(employees);
// Fetch locations
var dep1 = departments.at(0);
dep1.get('locations').fetch(); // 404. Because no server simulation for this service
/**
* Save
*/
var emp1 = employees.at(0);
var emp2 = employees.at(1);
// Create new employee for department 'admin'
var newEmp = new Employee({fname: 'Will', lname: 'Smith', works_for: 2});
newEmp.save();
console.log("New employee :");
console.log(newEmp);
// Add `newEmp` to MyApp.context.employees
employees.add(newEmp);
// Change and save employee's property
// will cause update on server
newEmp.save({'age': 25});
emp2.save({works_for: 1});
console.log("Emp2: ");
console.log(emp2);
@jdkanani
Copy link
Author

You can execute and play with this gist here.

@cmdelatorre
Copy link

there's an updated version of the jsfiddle here
Basically, the location of the underscore.js dependency was updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment