-
5 Feb 2012 9:14 AM #11
How about this ... ST1 patch that should accept strings and numbers as model ids ... whilst we wait for bug to be patched in ST2 ....
WARNING I've only done basic testing on this so far .. use at your own risk!
I suspect there are other bugs that remain around the setting of the phantom flag ....
Includes additional check when web storage quota is exceeded ....
Code:Ext.override(Ext.data.WebStorageProxy, { /** * @private * Saves the array of ids representing the set of all records in the Proxy * @param {Array} ids The ids to set * * PATCHED TO CHECK FOR STORAGE QUOTA OVERFLOW */ setIds : function(ids) { var obj = this.getStorageObject(), str = ids.join(","); obj.removeItem(this.id); if(!Ext.isEmpty(str)) { try { // + PATCH obj.setItem(this.id, str); } catch(e) { // + PATCH if((e.name).toUpperCase() == 'QUOTA_EXCEEDED_ERR') { // + PATCH // do something here (fire error event, etc.) // only when in the desktop ... iPad will prompt you Ext.Msg.alert('WebStorageProxy', 'You have exceeded your local storage quota'); } // + PATCH // else throw event to caller // + PATCH } // + PATCH } }, // PATCHED TO CHECK FOR DUPLICATE IDS create: function(operation, callback, scope) { var records = operation.records, length = records.length, ids = this.getIds(), id, record, i; operation.setStarted(); for (i = 0; i < length; i++) { record = records[i]; if (record.phantom) { record.phantom = false; id = this.getNextId(); } else { id = record.getId(); } this.setRecord(record, id); // only add if not already in the key // + PATCH if (ids.indexOf(id) < 0){ // + PATCH ids.push(id); } // + PATCH } this.setIds(ids); operation.setCompleted(); operation.setSuccessful(); if (typeof callback == 'function') { callback.call(scope || this, operation); } }, /** * @private * Fetches a model instance from the Proxy by ID. Runs each field's decode function (if present) to decode the data * @param {String} id The record's unique ID * @return {Ext.data.Model} The model instance * * PATCHED TO ALLOW FOR STRING OR INTEGER MODEL ID */ getRecord: function(id) { if (this.cache[id] == undefined) { var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))), data = {}, Model = this.model, fields = Model.prototype.fields.items, length = fields.length, i, field, name, record; for (i = 0; i < length; i++) { field = fields[i]; name = field.name; if (typeof field.decode == 'function') { data[name] = field.decode(rawData[name]); } else { if (field.type.type == 'date') { // +patch data[name] = new Date(rawData[name]); // +patch } else { // +patch data[name] = rawData[name]; } // +patch } } record = new Model(data, id); // @TODO: make sure we don't have to set phantom to false. we give it an id, so it shouldn't // be phantom after we created it right? // record.phantom = false; this.cache[id] = record; } return this.cache[id]; }, /** * Saves the given record in the Proxy. Runs each field's encode function (if present) to encode the data * @param {Ext.data.Model} record The model instance * @param {String} id The id to save the record under (defaults to the value of the record's getId() function) * * PATCHED TO ALLOW FOR STRING OR INTEGER MODEL ID */ setRecord: function(record, id) { if (id) { record.setId(id); } else { id = record.getId(); } var rawData = record.data, data = {}, model = this.model, fields = model.prototype.fields.items, length = fields.length, i = 0, field, name, obj, key; for (i = 0; i < length; i++) { field = fields[i]; name = field.name; if (typeof field.encode == 'function') { data[name] = field.encode(rawData[name], record); } else { if (field.type.type == 'date' && Ext.isDate(rawData[name])) { // + PATCH data[name] = rawData[name].getTime(); // + PATCH } else { // + PATCH data[name] = rawData[name]; } // + PATCH } } obj = this.getStorageObject(); key = this.getRecordKey(id); //keep the cache up to date this.cache[id] = record; //iPad bug requires that we remove the item before setting it obj.removeItem(key); obj.setItem(key, Ext.encode(data)); }, /** * @private * Returns the array of record IDs stored in this Proxy * @return {Array} The record IDs. Each is cast as a Number * * PATCHED TO ALLOW FOR STRING OR INTEGER MODEL ID */ getIds: function() { var ids = (this.getStorageObject().getItem(this.id) || "").split(","), length = ids.length, i, idType = this.getModelIdType(); // + PATCH if (length == 1 && ids[0] === "") { ids = []; } else { // cast to numbers if model id is a number too if (idType === 'number'){ // + PATCH for (i = 0; i < length; i++) { // + PATCH ids[i] = parseInt(ids[i], 10); } // + PATCH } } return ids; }, /* * NEW METHOD FOR PATCH TO ALLOW FOR STRING OR INTEGER MODEL ID * get data type of model * @return {String} data type of the model id */ getModelIdType: function(){ // has this already been checked? // assumes that models won't change their key type dynamically! if (this.modelIdType){ return this.modelIdType; } var model = this.model.prototype, idProperty = model.idProperty idField = model.fields.get(idProperty); this.modelIdType = 'number'; // if idProperty not found in field list -> will be a generated integer if (idField){ this.modelIdType = idField.type.type; } // handle other configuration values if (this.modelIdType === 'int'){ this.modelIdType = 'number'; } return this.modelIdType; }, //inherit // PATCHED TO ALLOW FOR STRING OR INTEGER MODEL ID destroy: function(operation, callback, scope) { var records = operation.records, length = records.length, ids = this.getIds(), //newIds is a copy of ids, from which we remove the destroyed records newIds = [].concat(ids), i, // to ensure correct casting idType = this.getModelIdType(); for( i = 0; i < length; i++) { // fix to ensure both numeric and string entries are matched -> removed if( idType === 'number' ) { // + PATCH newIds.remove(records[i].getId()); // } else { // + PATCH newIds.remove(records[i].getId() + ''); // + PATCH } // + PATCH this.removeRecord(records[i], false); } this.setIds(newIds); if( typeof callback == 'function') { callback.call(scope || this, operation); } } });
Thank you for reporting this bug. We will make it our priority to review this report.
Similar Threads
-
[OPEN-257] WebStorageProxy always removes first record
By emm in forum Sencha Touch 1.x: BugsReplies: 2Last Post: 15 Sep 2010, 8:39 PM -
Combobox with array returns text instead of value
By zvucini in forum Ext 2.x: Help & DiscussionReplies: 2Last Post: 4 Oct 2008, 3:52 PM -
Store collection returns empty array
By Padster in forum Ext 2.x: Help & DiscussionReplies: 4Last Post: 18 Sep 2008, 9:11 AM -
Date.getWeekOfYear sometimes returns an array of characters
By r8dhex in forum Ext 1.x: BugsReplies: 1Last Post: 22 Jun 2007, 9:10 AM -
Make Date.parseDate accept an array of possible format strings
By corey.gilmore in forum Community DiscussionReplies: 2Last Post: 30 May 2007, 5:51 PM


Reply With Quote