PDA

View Full Version : [FIXED] [4.2.0 / 4.2.1.-beta1] model load width emtpy result array brings an error



orbiz3
18 Apr 2013, 2:46 AM
REQUIRED INFORMATION

Ext version tested:

Ext 4.2.0 GA / 4.2.1.744-beta

Browser versions tested against:


FF 20.0.1 (firebug 1.11.2 installed)

Description:

If you try to load a model with a proxy ([your-model].load(...), and the resultset is empty, I get an error in firebug:
TypeError: record is undefined
if (!record.hasId()) {
In ExtJS 4.1.0 GA it's not a problem, if the resultset is empty
When it's empty, the model is undefined

Steps to reproduce the problem:

define a model with a ajax proxy and a json-reader
create an simple json-file (look at test-case) with an empty result array
get your model
load your model via: [your-model].load(id, {})
an error comes up -> "record is undefined" line: 69683 (ext-all-debug.js)
-> width ExtJS 4.1.0 GA you get on your success-methode at first arguments a model that was undefined

The result that was expected:

on ExtJS 4.1.0 GA the result of an empty resultset of a ajax-reqest was a model that was undefined

The result that occurs instead:

an error occurs

Test Case:

a user.json-File with a resultset:


{
success: true,
total: 1,
users: [
{ id: 1, name: 'Test-User' , email: 'TEST-Email'}
]
}


the user.json-File to reproduce the error:


{
success: true,
total: 0,
users: []
}


The test.html page:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="extjs/4.2.0/resources/css/ext-all.css"/>
<script type="text/javascript" src="extjs/4.2.0/ext-all-debug.js" charset="UTF-8"></script>
<script language="javascript" type="text/javascript" charset="UTF-8">
Ext.application({
name: 'Test',
launch: function() {
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'email'],
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
});

var user = Ext.ModelManager.getModel('User');
var userID = 1;
user.load(userID, {
success: function(user) {
console.log("argum", arguments)
if(user){
console.log("User found: " + user.getId() + ' - ' + user.get('name') + ' - ' + user.get('email'));
}else{
console.log("No User width ID: " + userID);
}
}
});



}
});
</script>
</head>
<body></body>
</html>



Possible fix:

line: 69683 - ext-all-debug.js



load: function(id, config) {
config = Ext.apply({}, config);
config = Ext.applyIf(config, {
action : 'read',
id : id
});
var operation = new Ext.data.Operation(config),
scope = config.scope || this,
record = null, callback;
callback = function(operation) {
if (operation.wasSuccessful()) {

// Why you don't check, if the the result record exists?
// In my test-case the record is undefined
record = operation.getRecords()[0];
if (!record.hasId()) {
record.setId(id);
}
Ext.callback(config.success, scope, [record, operation]);
} else {
Ext.callback(config.failure, scope, [record, operation]);
}
Ext.callback(config.callback, scope, [record, operation]);
};
this.getProxy().read(operation, callback, this);
}

Operating System:

Win7


Comment

I don't know if this is a bug, but in ExtJS 4.1.0 it works (empty result brings an empty model)

Did I miss something on upgrade from ExtJS 4.1.0 to ExtJS 4.2.0 ?

slemmon
18 Apr 2013, 7:08 AM
Thanks for the report! I have opened a bug in our bug tracker.

evant
2 May 2013, 4:56 PM
The response returned by the server is a bit questionable. We're asking it to load a single model and it means it doesn't exist or couldn't load it. Is that a success? I'd say it's not, because we don't end up with what we wanted from the server.

Even if we do return success, it's still a failure because there's no data. As such, the code will change so that it will be able to handle a combination of



success: true,
items: []


However, it will fire the failure callback.

orbiz2
3 May 2013, 12:19 AM
The response returned by the server is a bit questionable. We're asking it to load a single model and it means it doesn't exist or couldn't load it. Is that a success? I'd say it's not, because we don't end up with what we wanted from the server.

Even if we do return success, it's still a failure because there's no data. As such, the code will change so that it will be able to handle a combination of



success: true,
items: []


However, it will fire the failure callback.


I don't really get why you consider an empty result set a failure state.

I understand success:false to indicate an actual error state, i.e. there was an exception thrown server side or similar, and could be used to indicate that a record couldn't be loaded. But a result set being empty does not simply imply a failure occurred. Do you know of a single DB driver that indicates an error state when a query returns an empty result set?

When loading a model using a surrogate key, one could perhaps considered an empty result a failure state. But some shops have legacy schemas and use natural keys too. Imagine a scenario where a client needs to check the uniqueness of an email address, which is the natural primary key in a table, and has only a CRUD interface to do so. How do you check for uniqueness? Until this bug, you could send a read operation to the server, and check for an empty result set. success:true, count:0...no exception has been thrown, no kittens were harmed, just an empty result set.

Now imagine your shop has many such scenarios and a code base which depends on such requests NOT being considered failures? Time to refactor? I ask why.

Sam

evant
3 May 2013, 5:23 PM
But we're explicitly asking to load a single model. If, at all the end of it, you don't get a model back, surely that's a "failure", because it was unable to achieve the result.

Though it may not make sense for your use case, I think it would be an expected behaviour to fail if there are no records returned.

orbiz2
5 May 2013, 10:50 PM
Expected behavior for me would be to have my failure callback called if the server returned success:false.

What exactly is the purpose of the condition:

if (operation.wasSuccessful()) {
...if not to determine if the operation was a success or not?

So ExtJS will now ignore the (authoritative) response from the server indicating that the operation was successful, only to make a decision about its validity for me?

Can you provide me any other reason why this behavior should be changed other than your personal interpretation of well-formedness?

C.Parcell
9 Jul 2013, 8:15 AM
What is the status of this? I am having this same issue.

ExtJS 4.2.1.883

record is undefined

operation.wasSuccessful() is returning true when no records are returned.

If you have done something wacky with what or how you define success, then you may want to also check if record == undefined.

Or is there some other process to check for records prior than requesting them?

incutonez
2 Jan 2014, 7:37 AM
I'm having this issue with the latest build of 4.2.1 as well. My issue is that some models do not contain data for a certain hasOne relationship, so if I try to use the getter on these models (with no data for the relationship), I get the error:

TypeError: record is undefined (ext-all-dev.js: 100283)
if (!record.hasId()) {

I can't even call the getter and then check to see if I got something returned... it just stops the show completely, but that's because record is undefined, and it's not being checked for in that if statement on line 100283.

Anyway, my current work-around will be using the model's getAssociatedData (http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Model-method-getAssociatedData) function, and checking to see if my getter exists in there... if it does, proceed to use it, otherwise, never call it.