PDA

View Full Version : Model.save() breaks if server doesn't respond with updated record data



charris
24 Oct 2011, 12:40 PM
Model.save() currently seems to break if the server does NOT respond with data for the object that was just created/updated. For example, if the server just responds with a success message, save() will break.

From src/data/Model.js:1152 (4.0.6):


save: function(options) {
...
callback = function(operation) {
if (operation.wasSuccessful()) {
record = operation.getRecords()[0]; <-- getRecords() return an empty array, so record = undefined
me.set(record.data); <-- this breaks because record is undefined
...
}

Again, this is only the case if the server does not respond with text (e.g., JSON) for the model that was just saved/updated.

Would the dev team please consider modifying Model.save() such that attempting to update itself after the operation is optional? Not every server API responds with the object that was just created/updated.

charris
24 Oct 2011, 4:05 PM
I was able to come up with a work-around by using a custom proxy for the model, and overriding the update function:

Ext.define('kpc.util.CustomRestProxy', { extend: 'Ext.data.proxy.Rest',
alias: 'proxy.kpc.util.CustomRestProxy',
type: 'rest',


reader : {
root: 'data',
type: 'json',
messageProperty: 'message'
},


// Model.save() will call this function, passing in its own callback
update: function(operation, callback, scope) {


// Wrap the callback from Model.save() with our own logic
var mycallback = function(oper) {
// Delete the resultSet from the operation before letting
// Model.save's callback use it; this will
oper.resultSet = undefined;
callback(op);
};


return this.doRequest(operation, mycallback, scope);
}
});
In a nutshell, when my proxy is asked to do an update it makes sure operation.resultSet == undefined. This changes the return value for operation.getRecords() (which you can see in the code sample from my question). Here's what that function looks like (src/data/Operation.js):

getRecords: function() { var resultSet = this.getResultSet();
return (resultSet === undefined ? this.records : resultSet.records);
}
By ensuring that resultSet == undefined, operation.getRecords returns the model's current data instead of the empty result set (since the server isn't returning a result, only a simple success message). So when the callback defined in save() runs, the model sets its data to its current data.

r.vanelk
17 Nov 2011, 3:56 AM
Is this fixed in 4.1 ?

Dumbledore
18 Nov 2011, 5:18 AM
it will be great if this will be fixed in 4.0.8...

srfarley
9 Mar 2012, 5:17 AM
I have created a library called SenchaCouch containing a base Model class, and a Proxy implementation that handles all REST operations with a CouchDB server. It's available at:

https://github.com/srfarley/sencha-couch

(https://github.com/srfarley/sencha-couch)I was able to use the code in this thread, so thanks very much to Clint Harris!

hardwickj
26 Mar 2012, 8:17 PM
I might also add that, thanks to their choice on how to apply the response data, any associations that are returned in your save are also *NOT* applied to the model. So if a save operation causes associations to be modified and your server returns those, too bad. The current default behavior discards them.