In my Backbone application I have a model consisting of a couple of sub-models as parameters.
I define it so:
app.Models.Account = Backbone.Model.extend({
    initialize : function( ) {
        this.set( { 
                info     : new app.Models.Info(),
                logins   : new app.Collections.Logins(),
                billing  : new app.Models.Billing(),
            } );
    }
});
The problem is when fetching and saving. When I fetch for example the JSON response includes 
an object for info, an array for logins and an object for billing. Backbone automatically assigns them as normal parameters which means the sub-models are overridden with a simple object.
My current solution is to override the fetch method for the model like so:
    fetch: function( options ) {
      options = options ? _.clone(options) : {};
      var model = this;
      var success = options.success;
      options.success = function(resp, status, xhr) {
        resp = model.parse( resp, xhr );
        model.get('info').set(resp.info);
        model.get('logins').reset(resp.logins);
        model.get('billing').set(resp.billing);
        if (success) success(model, resp);
      };
      options.error = Backbone.wrapError(options.error, model, options);
      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    }
however this is only for fetch. And since the updated status of the model created is returned when calling the save() method I have to also override the save() method.
Are there any good approaches to solve this issue?
Perhaps overriding the set() method could work, however I fear that would mean that I would be beginning to go astray from the Backbone codebase.
I also thought about using the parse method like so
    parse : function ( response ) {
        this.model.get('info').set(response.info);
        response.info = this.model.get('info');
        this.model.get('logins').reset(response.logins);
        response.logins = this.model.get('logins')
        this.model.get('billing').set(response.billing);
        response.billing = this.model.get('billing');
        return response;
    }
which would create a reference to the already updated sub model.
I generally use parse for sub-models, as in your second example (though note that you need to return response at the end). I think this is conceptually accurate, as parse is the appropriate place for transforming the server-side representation into a client-side one. I believe this should work for save as well, though I haven't tested it, since parse is called on the save response too.
In my experience, overriding set is nothing but trouble - it tends to have unintended side-effects, and is better avoided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With