Search code examples
javascriptbackbone.jsbackbone.js-collectionsbackbone-model

Different model types in one collection Backbone


Backbone 1.1.2
Underscore 1.7.0
jQuery 1.11.1

I have a single collection that holds messages. My messages can be be of different types (and the endpoints in the api are different for each type, but I have an endpoint that allows me to do one request and get all the messages)

When Collection.fetch() I need to be able to define which model to use when populating the collection based on existing properties.

I have tried as suggested here: A Backbone.js Collection of multiple Model subclasses as well as the backbone documentation backbonejs.org

My code looks like this

model: function (attr, options) {
    if(attr.hasOwnProperty('prop')){
        return new PropModel(attr,options);
    }
    else if(attr.hasOwnProperty('another_prop')){
        new AnotherPropModel(attr,options);
    }
},

the attr value is just one big array of objects, so without traversing somehow this solution makes no sense to me and its obvious why it doesn't work.

Am I handling this correctly is there another way to do this?

---UPDATE----

I have also tried doing this in the Parse Function of the collection and my collection is just empty

parse: function (resp, options) {
    _.each(resp, _.bind(function (r) {
        console.log(this);
        if(r.hasOwnProperty('prop')){
            this.add(new PropModel(r));
        }else{
            this.add(new AnotherPropModel(r));
        }
    },this));
}

Solution

  • So the solution was a mix of using model function and return.

    Here goes the explanation:

    First off we have the parse function which is just an entry point for us to alter a response that we receive from our server

    parse: function (resp, options) {
        return resp;
    }
    

    In my case, the server was returning an Object of Object as

    {{1:data},{2:data}}
    

    Firstly this is strange and obviously needs to be resolved. The IMPORTANT POINT IS: When backbone assess the response return from parse, it needs to decide where to break off for each model as in what defines a new model.

    Backbone sees objects as a single model and as in my case, I had one big object, I was getting one big model... this is why the attrs argument in model function was one big mush of data.

    So I simply altered my response in the parse function and Voila!! everything in model function worked as expected:

    Here is the code:

    model: function (attr, options) {
        if(attr.hasOwnProperty('prop')){
            return new PropModel(attr,options);
        }
        else if (attr.hasOwnProperty('anotherProp')){
            return new AnotherPropModel(attr,options);
        }
    },
    
    parse: function (resp, options) {
        var response = [];
        _.each(resp, _.bind(function (r) {
            response.push(r);
        },this));
        return response;
    }
    

    Im sure there is a better way to resolve the object to array, but for now this works and I'm smiling again!!

    This article lead me to the solution: A collection of muppets