0

I have a Backbone.Model which looks something like:

var FooModel = Backbone.Model.extend({
    defaults: {
        details: '',
        operatingSystem: ''
    };
});

There are many instances of FooModel which are stored in a collection:

var FooCollection = Backbone.Collection.extend({
    model: FooModel
});

FooModel's OperatingSystem is a property which only needs to be calculated once and is derived asynchronously. For example:

chrome.runtime.getPlatformInfo(function(platformInfo){
    console.log("Operating System: ", platformInfo.os);
});

If I perform this logic at the FooModel level then I will need to perform the logic every time I instantiate a FooModel. So, I think that this operation should be performed at a higher level. However, it is bad practice to give properties to a Backbone.Collection.

As such, this leaves me thinking that I need a parent model:

var FooParentModel = Backbone.Model.extend({
    defaults: {
        platformInfo: '',
        fooCollection: new FooCollection()
    },

    initialize: function() {
        chrome.runtime.getPlatformInfo(function(platformInfo){
            this.set('platformInfo', platformInfo);
        }.bind(this));
    },
    //  TODO: This will work incorrectly if ran before getPlatformInfo's callback
    createFoo: function(){
        this.get('fooCollection').create({
            details: 'hello, world',
            operatingSystem: this.get('platformDetails').os
        });
    }
});

This works and is semantically correct, but feels over-engineered. The extra layer of abstraction feels unwarranted.

Is this the appropriate way to go about giving a property to a model?

Community
  • 1
  • 1
Sean Anderson
  • 27,963
  • 30
  • 126
  • 237

1 Answers1

0

Although Backbone Collections may not have attributes, they may have properties (as well as any object) which you can use to store shared data.

var FooCollection = Backbone.Collection.extend({
    model: FooModel
    initialize: function() {
        this.platformInfo = null; // shared data
        chrome.runtime.getPlatformInfo(function(platformInfo){
            this.platformInfo = platformInfo;
        }.bind(this));
    },
    // wrapper to create a new model within the collection
    createFoo: function(details) {
        this.create({
            details: details,
            operatingSystem: this.platformInfo? this.platformInfo.os : ''
        });
    }});
});
hindmost
  • 7,125
  • 3
  • 27
  • 39
  • Of course a collection can have a property, but I get the impression that this is bad practice because Backbone doesn't provide 'defaults' for collections. Do you think this is true? – Sean Anderson Oct 20 '14 at 16:22
  • Why you need `defaults` in your case? `platformInfo` property get default value (`null`) in `initialize` method which is called from collection's constructor. – hindmost Oct 20 '14 at 18:22