fix(ngResource): don't convert literal values into Resource objects when isArray is true

Previously non-object literals would be thrown out of Resource responses with isArray===true, or
otherwise converted into Objects (in the case of string literals). The reason for this is because
shallowClearAndCopy iterates over keys, and copies keys into the destination. Iterating over String
keys results in integer keys, with a single-character value.

Not converting non-objects to Resources means that you lose the ability to perform Resource operations
on them. However, they become usable as strings, numbers, or booleans, which is important.

In the future, it would be useful to make these useful as Resources while still retaining their primitive
value usefulness.

Closes #6314
Closes #7741
This commit is contained in:
Caitlin Potter
2014-06-07 14:04:04 -04:00
committed by rodyhaddad
parent 81b7e5ab0e
commit f0904cf12e
2 changed files with 37 additions and 7 deletions

View File

@@ -522,23 +522,32 @@ angular.module('ngResource', ['ng']).
extend({}, extractParams(data, action.params || {}), params),
action.url);
var promise = $http(httpConfig).then(function(response) {
var promise = $http(httpConfig).then(function (response) {
var data = response.data,
promise = value.$promise;
promise = value.$promise;
if (data) {
// Need to convert action.isArray to boolean in case it is undefined
// jshint -W018
if (angular.isArray(data) !== (!!action.isArray)) {
throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +
'response to contain an {0} but got an {1}',
action.isArray?'array':'object', angular.isArray(data)?'array':'object');
throw $resourceMinErr('badcfg',
'Error in resource configuration. Expected ' +
'response to contain an {0} but got an {1}',
action.isArray ? 'array' : 'object',
angular.isArray(data) ? 'array' : 'object');
}
// jshint +W018
if (action.isArray) {
value.length = 0;
forEach(data, function(item) {
value.push(new Resource(item));
forEach(data, function (item) {
if (typeof item === "object") {
value.push(new Resource(item));
} else {
// Valid JSON values may be string literals, and these should not be converted
// into objects. These items will not have access to the Resource prototype
// methods, but unfortunately there
value.push(item);
}
});
} else {
shallowClearAndCopy(data, value);

View File

@@ -1044,6 +1044,27 @@ describe("resource", function() {
$httpBackend.flush();
expect(user).toEqualData([ {id: 1, name: 'user1'} ]);
});
it('should not convert string literals in array into Resource objects', function() {
$httpBackend.expect('GET', '/names.json').respond(["mary", "jane"]);
var strings = $resource('/names.json').query();
$httpBackend.flush();
expect(strings).toEqualData(["mary", "jane"]);
});
it('should not convert number literals in array into Resource objects', function() {
$httpBackend.expect('GET', '/names.json').respond([213, 456]);
var numbers = $resource('/names.json').query();
$httpBackend.flush();
expect(numbers).toEqualData([213, 456]);
});
it('should not convert boolean literals in array into Resource objects', function() {
$httpBackend.expect('GET', '/names.json').respond([true, false]);
var bools = $resource('/names.json').query();
$httpBackend.flush();
expect(bools).toEqualData([true, false]);
});
});
describe('get', function(){