Sandy Gifford
Sandy Gifford

Reputation: 8136

Overriding Model.parse When Using Collection.reset

I need to use Model.parse to change the structure of incoming JSON; I also need to feed data into my collection using Collection.reset (we're drawing data from a plugin, not directly from a server). After a lot of effort, it seems to me that parse is only called when Collection.fetch is used, and not when passing data with reset or when feeding the JSON directly into the collection constructor (the documentation appears to agree).

Is there some way to force Backbone to pass the raw model object to parse for all cases in which new data is fed to it?

Right now I'm processing the raw object model in a separate function before passing it to reset, and while this does work, I find it to be a pretty unsatisfying solution. I'm also incredibly new to Backbone, so I'm vaguely suspicious that I'm just misunderstanding the relation between parse/reset/fetch.

Upvotes: 0

Views: 112

Answers (1)

ivarni
ivarni

Reputation: 17878

Yes, the purpose of reset is to load a collection with either fully fledged Models or raw model attribute hashes which would be why parse is not invoked.

Your workaround doesn't really sound that bad to me in theory. The way I would do that is to run the data I wanted to put in the collection through the underscore.js map function which is a good fit for this usecase in my opinion.

Consider the code in this plnkr

var MyModel = Backbone.Model.extend({

    parse: function(data) {
      return {
        text: data.text.toUpperCase() 
      }
    }

});

var MyCollection = Backbone.Collection.extend({

  model: MyModel

});

var collection = new MyCollection();

var arr = [
  { text: 'abc' },
  { text: 'cde' }
];


collection.reset(arr);
console.log(collection.pluck('text'));

collection.reset(_.map(arr, MyModel.prototype.parse));
console.log(collection.pluck('text'));

There's a MyModel with a parse function, and two ways of resetting a collection made for that model. The second approach uses _.map instead of just passing the raw data. The map function takes an array and a function reference and returns a new array containing the objects of the input function transformed by the second argument, in this case that function is the model's parse.

If you still don't like that syntax you could try to provide a custom Sync so it talks directly with the plugin you're getting data from instead of using a REST backend. That's a bit more work though and I personally don't think it's really worth the effort. You'd just end up doing pretty much the same thing but in a more contrived way but if you're also going to be handling deleting and updating data through the same plugin it's probably cleaner.

Upvotes: 2

Related Questions