How can I pass properties into a Backbone.Model which I do not wish to be treated as attributes?

I have a Backbone.Model named Company.
My Company model has an Employees Backbone.Collection containing Employee models.

When I instantiate my Employee models to populate the Employees collection I wish for them to have a reference to the Company they belong to. But when I pass Company in it becomes one of the attributes of Employee. This is an issue when I go to save the Employee because the toJSON method will contain a Company object, when in the database all I store is the foreign key integer company_id.

I wish there was a second parameter for Backbone.Model that accepted model properties that are not part of the core attributes. How can I get around this? I realize I could instantiate my Employee models and afterwards attach the Company, but I really want to do all the assignments in a traditional “constructor” rather than attach properties from outside.

e.g.:

Employee = Backbone.Model.extend({});

Employees = Backbone.Collection.extend({
  model: Employee
});

Company = Backbone.Model.extend({
  initialize: function() {
    this.employees = new Employees({});
  }
});

c1 = new Company({id: 1});
e = new Employee({name: 'Joe', company_id: 1, company: c1});
c1.employees.add(e);

e.get('company'); // => c1

e.save(); // BAD -- attempts to save the 'company' attribute, when in reality I only want to save name and company_id


//I could do
c2 = new Company({id: 2});
e2 = new Employee({name: 'Jane', company_id: 2});
e2.company = c2;
c2.employees.add(e);

e.company; // => c2

//I don't like this second method because the company property is set externally and I'd have to know it was being set everywhere in the code since the Employee model does not have any way to guarantee it exists

You could always read it manually from the options object and store it however you like. The options are passed as the second argument to the initialize method:

var Employee = Backbone.Model.extend({
    initialize: function(attributes, options) {
        this.company = options.company;
    }
});
var shesek = new Employee({name: 'Nadav'}, {company: Foobar});

Alternatively, you can use Backbone-relational which makes it much easier to handle models that contains references to other models and collection.

Read More:   Typescript function taking one or array of objects

You might also be interested in making toJSON() recursive (a patch I submitted to their issue tracker)

You can override the save method on the model to convert the save record to only send name and company id.

Employee = Backbone.Model.extend({
   save: function() {
       var toSend = {name:this.get('name'),company_id: this.get('company').get('id')}
       // method to send toSend to server.
   }
});


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Similar Posts