PDA

View Full Version : [4.0.6/7] Proxy reader uses wrong model to read response



charris
8 Nov 2011, 10:32 AM
I believe the following scenario reveals a bug:
Define a model class, ModelA, with a proxy config
Define another model class, ModelB, also with a proxy config
Call ModelB.load(...)
Issue: The 'success' callback for ModelB receives an instance of ModelA. Specifically, it seems that the reader used by ModelB's proxy is incorrectly using a ModelA instance to read the response.

Note: Defining ModelB BEFORE ModelA causes the issue to go away.

I have a working test case here (open your JavaScript console and click Run to see output): http://jsfiddle.net/clint_harris/GZ6gZ/

This test case is the exact same code, but ModelB is defined BEFORE ModelA, which hides the error symptoms: http://jsfiddle.net/clint_harris/3hYmV/

Here's the code for the test case showing the problem:

Ext.define('MyProxy', { extend: 'Ext.data.proxy.Rest',
alias: 'proxy.MyProxy',
reader : {
root: 'data',
type: 'json',
messageProperty: 'message'
},
doRequest: function(operation, callback, scope) {
console.log('Proxy is making request...');
if( this.shouldUseModel != this.reader.model.modelName ) {
console.error('Error: Proxy reader should be using '+this.shouldUseModel+' but is using '+this.reader.model.modelName+' instead');
}

this.callParent(arguments);
}
});


Ext.define('ModelA', {
extend: 'Ext.data.Model',
fields: [ {name: 'propertyA', type: 'string'} ],
modelAFcn: function(){},
proxy : {
type: 'MyProxy',
shouldUseModel: 'ModelA',
// Load JSON sample data from https://gist.github.com/1348050
url: '/gh/gist/response.json/1348050'
}
});


Ext.define('ModelB', {
extend: 'Ext.data.Model',
fields: [ {name: 'propertyB', type: 'string'} ],
modelBFcn: function(){},
proxy : {
type: 'MyProxy',
shouldUseModel: 'ModelB',
// Load JSON sample data from https://gist.github.com/1348325
url: '/gh/gist/response.json/'
}
});


ModelB.load('1348325', {
success: function(model, operation) {
console.log('Loaded what SHOULD be a ModelB instance:', model);
model.modelBFcn(); //<-- ERROR: modelBFcn doesn't exist because model
// is instance of ModelA
}
});

charris
8 Nov 2011, 10:39 AM
Note that a temporary work-around I've found is to hard-code the proxy config portion of each model class with the model class name. For example:


Ext.define('MyAModel', {
extend: 'Ext.data.Model',
fields: //...
proxy : {
type: 'rest',
url: //...
model: 'MyAModel'
}
});

Ext.define('MyBModel', {
extend: 'Ext.data.Model',
fields: //...
proxy : {
type: 'rest',
url: //...
model: 'MyBModel'
}
});

mitchellsimoens
8 Nov 2011, 1:43 PM
I'm thinking that this is because you have specified the reader Object in your new proxy. Since it is set as a config, Objects and Arrays are then shared among all instances. If you set the reader within a method then it should create a new reader when a new instance of that proxy is created.

charris
8 Nov 2011, 2:24 PM
Hey Mitchell, thanks for taking a look at this.

To be clear, I only see this problem if "ModelA" is defined before "ModelB". When I reload my application, sometimes ModelB is defined first; in that case the reader for ModelB's proxy correctly uses a ModelB instance and the reader for ModelA's proxy correctly uses a ModelA instance.

In other words, it doesn't seem like any objects/arrays are always being shared.

Do you think this is a bug, a documentation problem, or user error? It took me a few hours to debug the issue and I thought I was using the API as documented.

Thanks!

charris
8 Nov 2011, 4:01 PM
For anyone else who comes across this, the work-around I think Mitchell is suggesting involves setting the reader similar to as follows (i.e., using setReader() in the constructor instead of defining a "reader: {...}" config property on the proxy class). I have tested it and it does work.

Ext.define('MyProxy', {
extend: 'Ext.data.proxy.Rest',
alias: 'proxy.MyProxy',
constructor : function(config) {
this.callParent(arguments);
this.setReader({
root: 'data',
type: 'json'
});
return this;
},
doRequest: function(operation, callback, scope) {
console.log('Proxy is making request...');
if( this.shouldUseModel != this.reader.model.modelName ) {
console.error('Error: Proxy reader should be using '+this.shouldUseModel+' but is using '+this.reader.model.modelName+' instead');
}

this.callParent(arguments);
}
});

gps-ulm
28 Aug 2012, 2:05 AM
Hello,

I had the same problem and I put 2 bugfixes in the 4.1.1 source:

===================================================================
--- platform/src/data/AbstractStore.js (revision 2571)
+++ platform/src/data/AbstractStore.js (working copy)
@@ -296,6 +296,8 @@
// </debug>

me.model = Ext.ModelManager.getModel(me.model);
+ if ( Ext.isObject(me.proxy) )
+ me.proxy = Ext.apply( {}, me.proxy );

/**
* @property {Object} modelDefaults

and


--- platform/src/data/proxy/Proxy.js (revision 2571)
+++ platform/src/data/proxy/Proxy.js (working copy)
@@ -102,7 +102,7 @@
* @param {Object} config (optional) Config object.
*/
constructor: function(config) {
- config = config || {};
+ config = Ext.apply( {}, config || {} );

if (config.model === undefined) {
delete config.model;

perhaps this is useful for someone.

Regards,

Tobias Wagener