Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Aug 2010
    Posts
    35
    Vote Rating
    0
    yoorek is on a distinguished road

      0  

    Default 1.1.1 broke store.sync for modified records

    1.1.1 broke store.sync for modified records


    Since 1.1.1 store.sync() stopped work for records modified with record.set(fieldname, value);

    After store.sync() nothing happens though record.save() works!!!

    I looked at Ext.util.Stateful.set method code in 1.1.0 and it is changed drastically in 1.1.1.

    In 1.1.0 set method changes dirty flag with 1 line:

    Code:
    this.dirty = true
    In 1.1.1 set motkd changes dirty flag after checking conditions which are never true.
    First - field.persist ?? ok, I set it in model (why?) but then currentValue is undefined at raises error.

    Here is code in 1.1.1 that replaced one above line in 1.1.0:

    Code:
    if (field && field.persist && !me.isEqual(currentValue, value)) {
                    if (me.isModified(fieldName)) {
                        if (me.isEqual(modified[fieldName], value)) {
                            
                            
                            delete modified[fieldName];
                            
                            
                            me.dirty = false;
                            for (key in modified) {
                                if (modified.hasOwnProperty(key)){
                                    me.dirty = true;
                                    break;
                                }
                            }
                        }
                    } else {
                        me.dirty = true;
                        modified[fieldName] = currentValue;
                    }
                }

    After reverting to 1.1.0 everything works OK.

    What is the cause of such a "improvement" in crucial method ?

  2. #2
    Sencha User
    Join Date
    Oct 2011
    Location
    Germany
    Posts
    146
    Vote Rating
    10
    Möhre will become famous soon enough

      0  

    Default


    Beginner question: What´s the consequence of this bug?

    Does it mean that records that have been modified with record.set(fieldname, value) in 1.1.0 are gone in 1.1.1?

  3. #3
    Sencha User
    Join Date
    Aug 2010
    Posts
    35
    Vote Rating
    0
    yoorek is on a distinguished road

      0  

    Default


    Yes.

    In 1.1.0:

    Code:
    record.set('NAME', 'NewName');
    store.sync(); // UPDATE GOES TO STORAGE
    record.set('NAME', 'NewName2');
    record.save(); // UPDATE GOES TO STORAGE
    In 1.1.1

    Code:
    record.set('NAME', 'NewName');
    store.sync(); // NOTHING HAPPENS, USER CLOSES APP AND CHANGES ARE LOST 
    record.set('NAME', 'NewName2');
    record.save(); // UPDATE GOES TO STORAGE

  4. #4

  5. #5
    Sencha User MiamiCoder's Avatar
    Join Date
    Mar 2009
    Location
    Miami, FL
    Posts
    140
    Vote Rating
    2
    MiamiCoder is on a distinguished road

      0  

    Default


    I've been able to work around this in some scenarios with a call to setDirty on the model immediately before the sync call on the store.

  6. #6
    Sencha User
    Join Date
    Oct 2011
    Location
    Germany
    Posts
    146
    Vote Rating
    10
    Möhre will become famous soon enough

      0  

    Default


    Thanks, setDirty does the trick.

    Wow, you already updated your tutorial/blog. Fast guy

    Why does Sencha not have a complete unit testcase to avoid such bugs???

  7. #7
    Sencha User
    Join Date
    Nov 2011
    Posts
    4
    Vote Rating
    0
    urk is on a distinguished road

      0  

    Default Override

    Override


    Hi,

    This override works for me (don't worry about the number of lines, actually it's just two edited lines and an additional small function taken from the Sencha Touch 2 Developer Preview):

    Code:
    if (Ext.version == '1.1.1') {
        
        // fix: modified records are not marked as dirty and therefore ignored on store sync
        Ext.override(Ext.util.Stateful, {
            
            /**
             * Sets the given field to the given value, marks the instance as dirty
             * @param {String|Object} fieldName The field to set, or an object containing key/value pairs
             * @param {Mixed} value The value to set
             */
            set: function(fieldName, value) {
                var me = this,
                    fields = me.fields,
                    modified = me.modified,
                    convertFields = [],
                    field, key, i;
                
                /*
                 * If we're passed an object, iterate over that object. NOTE: we pull out fields with a convert function and
                 * set those last so that all other possible data is set before the convert function is called
                 */
                if (arguments.length == 1 && Ext.isObject(fieldName)) {
                    for (key in fieldName) {
                        if (!fieldName.hasOwnProperty(key)) {
                            continue;
                        }
                        
                        //here we check for the custom convert function. Note that if a field doesn't have a convert function,
                        //we default it to its type's convert function, so we have to check that here. This feels rather dirty.
                        field = fields.get(key);
                        if (field && field.convert !== field.type.convert) {
                            convertFields.push(key);
                            continue;
                        }
                        
                        me.set(key, fieldName[key]);
                    }
                    
                    for (i = 0; i < convertFields.length; i++) {
                        field = convertFields[i];
                        me.set(field, fieldName[field]);
                    }
                    
                } else {
                    if (fields) {
                        field = fields.get(fieldName);
                        
                        if (field && field.convert) {
                            value = field.convert(value, me);
                        }
                    }
                    // *** added line ***
                    currentValue = me.get(fieldName);
                    me[me.persistanceProperty][fieldName] = value;
                    
                    // *** edited line *** if (field && field.persist && !me.isEqual(currentValue, value)) {
                    if (!me.isEqual(currentValue, value)) {
                        if (me.isModified(fieldName)) {
                            if (me.isEqual(modified[fieldName], value)) {
                                // the original value in me.modified equals the new value, so the
                                // field is no longer modified
                                delete modified[fieldName];
                                // we might have removed the last modified field, so check to see if
                                // there are any modified fields remaining and correct me.dirty:
                                me.dirty = false;
                                for (key in modified) {
                                    if (modified.hasOwnProperty(key)){
                                        me.dirty = true;
                                        break;
                                    }
                                }
                            }
                        } else {
                            me.dirty = true;
                            modified[fieldName] = currentValue;
                        }
                    }
                    
                    // fix
                    me.dirty = true;
                    
                    if (!me.editing) {
                        me.afterEdit();
                    }
                }
            },
            
            // *** added function ***
            /**
             * Checks if two values are equal, taking into account certain
             * special factors, for example dates.
             * @private
             * @param {Object} a The first value
             * @param {Object} b The second value
             * @return {Boolean} True if the values are equal
             */
            isEqual: function(a, b){
                if (Ext.isDate(a) && Ext.isDate(b)) {
                    return a.getTime() === b.getTime();
                }
                return a === b;
            }
            
        });
        
    };
    Cheers,

    Uwe

  8. #8
    Sencha User
    Join Date
    Aug 2010
    Posts
    35
    Vote Rating
    0
    yoorek is on a distinguished road

      0  

    Default


    Thanks for the code.

    Actually I got my own solution - got rid of Sencha Touch.
    This kind of mistakes makes me sure ST is not ready for production - it seams they don't have QA at all.
    There are to many hacks and workarounds - spent 90% of time debugging framework and 10% developing application. Waste of time.
    Will give another try in year or two. Maybe.

  9. #9
    Sencha User
    Join Date
    Sep 2011
    Posts
    4
    Vote Rating
    0
    karthiktheraja is on a distinguished road

      0  

    Default Hi

    Hi


    I am also facing the same problem with sencha touch 1.1.1 , I tried with loadData(data, false),which removes existing data and adds new data in sencha touch 1.1.0 is not working with sencha 1.1.1 . I want to know whether this bug will be rectified in next version or any work around is needed .I am working with local storage .Please give your suggestion.Thanks

  10. #10
    Sencha User
    Join Date
    Aug 2010
    Posts
    35
    Vote Rating
    0
    yoorek is on a distinguished road

      0  

    Default


    My solution is to get rid off Sencha. I Lost 6 months with this kind of bugs. There are dozens of bugs older than six months. Breaking absolutely crucial part of data access with minor upgrade is embarassing - and nobody cares working on 2.0 that maybe in 1 year will be ready for production.
    Truth is we were tricked by Sencha - we thought that Alfa version of their product is ready to use because they named it 1.1.