I'm reporting this because it violates the principle of least surprise. Little things like this build up. Please take a page out of Rails' playbook and care about the numerous details that make things better for developers.

Steps to reproduce:


(1) Create a model (and corresponding store) with a calculated id field:



Code:



Ext.define('MyApp.model.SearchResult', {
extend: 'Ext.data.Model',

config: {
fields: [
{
name: 'id',
convert: function(id, searchResult){
return id ? id : (searchResult.data.record_type + '-' + searchResult.data.record_id);
}
},
{ name: 'record_id' },
{ name: 'record_type' },
{ name: 'record' }
]
}
});

(2) Load the store:


Code:



searchResults.load(function(){
firstResult = searchResults.first();
});
// GET [/search_results.json] -> { search_results: [{ record_id: 42, record_type: 'Person', record: {} }] }

(3) Load the store again:


Code:



searchResults.load(function(){
shouldBeFirstResult = searchResults.first();
});
// GET [/search_results.json] -> { search_results: [{ record_id: 42, record_type: 'Person', record: {} }] }

What's expected:


On the 2nd load, Touch finds the existing record in its cache and merges the data into the existing record.

What happens instead:


On the 2nd load, Touch creates a new record. Now there are 2 instances with the same ID. Chaos ensues.


Solution:


Ext.data.Model#constructor should run the id field through its convert fn before checking the cache for an existing record.