Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

updating Backbone submodels after fetch/save

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.

like image 975
Daniel Avatar asked Nov 23 '12 11:11

Daniel


1 Answers

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.

like image 51
nrabinowitz Avatar answered Sep 21 '22 03:09

nrabinowitz