Search code examples
backbone.jsbackbone.js-collections

Backbone.js Why is my default model present in a fetched collection?


I'm sure I'm missing something very basic. I'm setting up a collection of fetched objects

collection.fetch({reset: true})

based on a model that contains a 'defaults' property.

However, when I view the fetched collection in the console I have an extra model in it, which is set with the default attributes. Why is this happening? More importantly, how do I prevent it?

var diningApp = diningApp || {};

(function(){
"use strict";

diningApp.MenuItem = Backbone.Model.extend({
    defaults: {
        service_unit: null,
        course: null,
        formal_name: null,
        meal: null,
        portion_size: null,
        service_unit_id: null
    }
});

var MenuCollection = Backbone.Collection.extend({
    model: diningApp.MenuItem,

    url: '/api/dining/get_menus',

    parse: function(response){
        return response.menu_items;
    }
});

diningApp.menuCollection = new MenuCollection();
diningApp.menuCollection.fetch({reset: true});
})();

Here is a portion of the JSON response from the server:

{
  "status": "ok",
  "menu_items": [
  {
    "service_unit": "Faculty House",
    "course": "Entrees",
    "formal_name": "Local CF Fried Eggs GF",
    "meal": "BREAKFAST",
    "portion_size": "1 Egg",
    "service_unit_id": 0
  },
  {
    "service_unit": "Faculty House",
    "course": "Entrees",
    "formal_name": "CageFree Scrambled Eggs GF",
    "meal": "BREAKFAST",
    "portion_size": "2 eggs",
    "service_unit_id": 0
  }]
}

And here's the resulting collection in the console:

enter image description here


Solution

  • If you dig a bit into Backone's source code to check what happens when you reset a collection, you'll end looking at Collection.set. The lines of interest to your problem are :

    // Turn bare objects into model references, 
    // and prevent invalid models from being added.
    for (i = 0, l = models.length; i < l; i++) {
        attrs = models[i] || {};
        // ...
    

    This means that each falsy (false, null, etc.) item in the array is converted to an empty object before being cast into a model and receiving default values.

    Either

    • modify your server response to remove falsy values
    • or alter your parse method to clean up you array

      parse: function(response){
          return _.compact(response.menu_items);
      }