documentcloud/backbone — pull request #1534 by kellerds (2012-08-08 06:46:45+00:00)
Title: Fix case where model.save(model, {wait:true}) does not correctly merge 'serverAttrs' with the 'model.attributes' 

I've run into an issue where, when saving a model object with {wait:true}, attributes from the server are not correctly merged with the existing client-side model attributes. The root issue seems to be that Model.save()'s success function uses _.extend( attrs || {}, serverAttrs), not paying attention to the possibility that 'attrs' may not be a simple hash, but may instead be a Model object. If it is a Model object, then the serverAttrs are merged as top-level properties instead of into the model's 'attributes' hash, where they belong:

```javascript
options.success = function(resp, status, xhr) {
done = true;
var serverAttrs = model.parse(resp, xhr);
if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
if (!model.set(serverAttrs, options)) return false;
...
```

In the Model.set() function the code then does this:

```javascript
if (attrs instanceof Model) attrs = attrs.attributes;
```

which results in the loss of the top-level attributes we just merged from the 'serverAttrs' hash.

I propose that save()'s success function be changed to detect whether attrs is a Model object and extract the attributes this way:

```javascript
if (options.wait) serverAttrs = _.extend((attrs instanceof Model) ? attrs.attributes : attrs, serverAttrs);
```

Please advise if I'm missing something here. I suspect that the server modifying attributes in this manner is just not a common scenario, though it does seem valid.