Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Dec 2008
    Location
    Mainz
    Posts
    241
    Vote Rating
    1
    crp_spaeth is on a distinguished road

      0  

    Default [FEAT] [3.0rc1] Batch-save should work like the autosave

    [FEAT] [3.0rc1] Batch-save should work like the autosave


    Hi there Since i am working on a solution for a generic .net Proxy and Router for the Direct Class I need to know wich changes in Ext.Direct Philosophie are planed.

    I dived into the Ext Code again and find it kind of confusing that the batch methode works different than the automatically mechanism.


    Since Server-side validation for example can prevent a Record to be saved but it may stops one record to be saved it may saves other records just fine. So there ocurs an error while saving records on the server-side but there a still a few records saved...
    So how can the server tell the client wicht record has been saved and wich not?
    It would be much easier to have a transaction for every record to save. That would make it possible to return an exception when an error orcur and it would be much easier to rollback the records that failed to save.


    Ext.data.Store:

    PHP Code:
    /**
         * Send all {@link #getModifiedRecords modifiedRecords} to the server using the
         * api's configured save url.
         * @param {Object} options
         */
        
    save : function(rs) {
            
    rs rs || this.getModifiedRecords();
            if (!
    rs.length && !rs instanceof Ext.data.Record && !this.removed.length) {
                return 
    false;
            }
            var 
    action 'save';
            if (
    this.removed.length) {
                try {
                    
    this.execute('destroy'this.removed);
                }
                catch (
    e) {
                    throw 
    e;        // <-- just re-throw it for now...
                
    }
            }
            try {
                if (
    Ext.isArray(rs)) {
                    for (var 
    rs.length-1>= 0i--) {
                        if (
    rs[i].phantom === true) {
                            var 
    rec rs.splice(i1).shift();
                            if (
    rec.isValid()) {
                                
    this.execute('create'rec);
                            }
                        }
                    }
                }
                else if (
    rs.phantom) {
                    if (!
    rs.isValid()) {
                        return 
    false;
                    }
                    
    action 'create';
                }
                if (
    Ext.isArray(rs) && rs.length == 1) {
                    
    rs rs[0];
                }
                if (
    rs instanceof Ext.data.Record || rs.length 0) {
                    
    this.execute(actionrs);
                    return 
    true;
                }
                else {
                    
    // no more actions to execute.  They may have been spliced-out by create actions above.  just return true.
                    
    return true;
                }
            }
            catch (
    e) {
                throw 
    e;
            }
            return 
    true;
        }, 

    I would end up with something like this...
    PHP Code:
    /**
         * Send all {@link #getModifiedRecords modifiedRecords} to the server using the
         * api's configured save url.
         * @param {Object} options
         */
        
    save : function(rs) {
            
    rs rs || this.getModifiedRecords();
            if (!
    rs.length && !rs instanceof Ext.data.Record && !this.removed.length) {
                return 
    false;
            }
            var 
    action 'save';
            if (
    this.removed.length) {
                try {
                    
    this.execute('destroy'this.removed);
                }
                catch (
    e) {
                    throw 
    e;        // <-- just re-throw it for now...
                
    }
            }
            try {
                if (
    Ext.isArray(rs)) {
                    for (var 
    rs.length-1>= 0i--) {
                        var 
    rec rs.splice(i1).shift();
                        if (
    rec.phantom === true) {
                            if (
    rec.isValid()) {
                                
    this.execute('create'rec);
                            }
                        } else {
                            if (
    rec.isValid()) {
                                
    this.execute('save'rec);
                            }
                        }

                    }
                }
                else if (
    rs.phantom) {
                    if (!
    rs.isValid()) {
                        return 
    false;
                    }
                    
    action 'create';
                } else {
                            if (
    rs.isValid()) {
                                
    this.execute('save'rs);
                            }
                }
                else {
                    
    // no more actions to execute.  They may have been spliced-out by create actions above.  just return true.
                    
    return true;
                }
            }
            catch (
    e) {
                throw 
    e;
            }
            return 
    true;
        }, 

    (falls under the same category like http://extjs.com/forum/showthread.ph...928#post324928)

  2. #2
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Location
    Montreal
    Posts
    381
    Vote Rating
    0
    christocracy is on a distinguished road

      0  

    Default


    In fact, that's how I originally wrote Store#save. The Writer package was initially designed for Ext.Direct then expanded to handle all proxies. Since Ext.Direct will queue the transaction into one Ajax request, it worked great. I'll see what I can do once things settle down a bit.
    /**
    * @author Chris Scott
    * @business www.transistorsoft.com
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    *
    * @SenchaDevs http://senchadevs.com/developers/transistor-software
    * @twitter http://twitter.com/#!/christocracy
    * @github https://github.com/christocracy
    */

  3. #3
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Location
    Montreal
    Posts
    381
    Vote Rating
    0
    christocracy is on a distinguished road

      0  

    Default


    Oh, and that code you posted is rather dated. Store#save looks like this now:

    PHP Code:
    save : function() {
            if (!
    this.writer) {
                throw new 
    Ext.data.Store.Error('writer-undefined''Store.js');
            }

            
    // First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
            
    if (this.removed.length) {
                try {
                    
    this.execute(Ext.data.Api.DESTROYthis.removed);
                } catch (
    e) {
                    
    this.handleException(e);
                }
            }

            
    // Check for modified records.  Bail-out if empty...
            
    var rs this.getModifiedRecords();
            if (!
    rs.length) {
                return 
    true;
            }

            
    // Next check for phantoms within rs.  splice-off and execute create.
            
    var phantoms = [];
            for (var 
    rs.length-1>= 0i--) {
                if (
    rs[i].phantom === true) {
                    var 
    rec rs.splice(i1).shift();
                    if (
    rec.isValid()) {
                        
    phantoms.push(rec);
                    }
                }
                else if (!
    rs[i].isValid()) { // <-- while we're here, splice-off any !isValid real records
                    
    rs.splice(i,1);
                }
            }
            
    // If we have valid phantoms, create them...
            
    if (phantoms.length) {
                try {
                    
    this.execute(Ext.data.Api.CREATEphantoms);
                } catch (
    e) {
                    
    this.handleException(e);
                }
            }

            
    // And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
            
    if (rs.length) {
                try {
                    
    this.execute(Ext.data.Api.UPDATErs);
                } catch (
    e) {
                    
    this.handleException(e);
                }
            }
            return 
    true;
        }, 
    /**
    * @author Chris Scott
    * @business www.transistorsoft.com
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    *
    * @SenchaDevs http://senchadevs.com/developers/transistor-software
    * @twitter http://twitter.com/#!/christocracy
    * @github https://github.com/christocracy
    */

  4. #4
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Location
    Montreal
    Posts
    381
    Vote Rating
    0
    christocracy is on a distinguished road

      0  

    Default


    Ok, Ext.data.DirectStore does what you requested, wraps each record-action into a distinct Ext.Direct transaction.

    As it happens, DirectStore will actually work with an HttpProxy -- you'll get an Ajax request for each record though! I highly recommend using Ext.Direct for this.

    Committed to SVN.

    PHP Code:
    save : function(options) {
            if (!
    this.writer) {
                throw new 
    Ext.data.Store.Error('writer-undefined''Store.js');
            }

            
    // First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
            
    if (this.removed.length) {
                for (var 
    0len this.removed.lengthleni++) {
                    try {
                        
    this.execute(Ext.data.Api.DESTROYthis.removed[i]);
                    }
                    catch (
    e) {
                        
    this.handleException(e);
                    }
                }
            }

            
    // Check for modified records.  Bail-out if empty...
            
    var rs this.getModifiedRecords();
            if (!
    rs.length) {
                return 
    true;
            }

            
    // Next create phantoms within rs...
            
    for (var rs.length-1>= 0i--) {
                if (
    rs[i].phantom === true) {
                    var 
    rec rs.splice(i1).shift();
                    if (
    rec.isValid()) {
                        try {
                            
    this.execute(Ext.data.Api.CREATErec);
                        } catch (
    e) {
                            
    this.handleException(e);
                        }
                    }
                }
                else if (!
    rs[i].isValid()) { // <-- while we're here, splice-off any !isValid real records
                    
    rs.splice(i,1);
                }
            }
            
    // And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
            
    if (rs.length) {
                for (var 
    0len rs.lengthleni++) {
                    try {
                        
    this.execute(Ext.data.Api.UPDATErs[i]);
                    }
                    catch (
    e) {
                        
    this.handleException(e);
                    }
                }
            }
            return 
    true;
        } 
    /**
    * @author Chris Scott
    * @business www.transistorsoft.com
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    *
    * @SenchaDevs http://senchadevs.com/developers/transistor-software
    * @twitter http://twitter.com/#!/christocracy
    * @github https://github.com/christocracy
    */

  5. #5
    Ext JS Premium Member dj's Avatar
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    573
    Vote Rating
    2
    dj has a spectacular aura about dj has a spectacular aura about dj has a spectacular aura about

      0  

    Default


    Hi Chris,

    thanks for this commit! I have a problem with it though...

    Ext.data.DirectStore was merely a small helper that helped you configure an Ext.data.Store for Ext.Direct. Now it has this override for #save and one has to use this helper class.
    But I regularly use an Ext.data.GroupingStore for my Ext.Direct-enabled stores because some grids of mine have GroupingViews.

    Couldn't you merge Ext.data.DirectStore#save into Ext.data.Store#save and introduce a new @cfg combineUpdates that switches the behavior?

    Something like this (copy&paste-only) solution:

    Ext.data.Store
    Code:
    //... 
    /** @cfg {boolean} combineUpdates <tt>true</tt> if store should send all updated records in one transaction. <tt>false</tt> if it should create a new transaction for every modified record.
    combineUpdates: true
    //...
        save : function() {
    if (this.combineUpdates) { // normal Ext.data.Store#save  
            if (!this.writer) {
                throw new Ext.data.Store.Error('writer-undefined', 'Store.js');
            }
    
            // First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
            if (this.removed.length) {
                try {
                    this.execute(Ext.data.Api.DESTROY, this.removed);
                } catch (e) {
                    this.handleException(e);
                }
            }
    
            // Check for modified records.  Bail-out if empty...
            var rs = this.getModifiedRecords();
            if (!rs.length) {
                return true;
            }
    
            // Next check for phantoms within rs.  splice-off and execute create.
            var phantoms = [];
            for (var i = rs.length-1; i >= 0; i--) {
                if (rs[i].phantom === true) {
                    var rec = rs.splice(i, 1).shift();
                    if (rec.isValid()) {
                        phantoms.push(rec);
                    }
                }
                else if (!rs[i].isValid()) { // <-- while we're here, splice-off any !isValid real records
                    rs.splice(i,1);
                }
            }
            // If we have valid phantoms, create them...
            if (phantoms.length) {
                try {
                    this.execute(Ext.data.Api.CREATE, phantoms);
                } catch (e) {
                    this.handleException(e);
                }
            }
    
            // And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
            if (rs.length) {
                try {
                    this.execute(Ext.data.Api.UPDATE, rs);
                } catch (e) {
                    this.handleException(e);
                }
            }
            return true;
    } else { // Ext.data.DirectStore#save 
    if (!this.writer) {
                throw new Ext.data.Store.Error('writer-undefined', 'Store.js');
            }
    
            // First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
            if (this.removed.length) {
                for (var i = 0, len = this.removed.length; i < len; i++) {
                    try {
                        this.execute(Ext.data.Api.DESTROY, this.removed[i]);
                    }
                    catch (e) {
                        this.handleException(e);
                    }
                }
            }
    
            // Check for modified records.  Bail-out if empty...
            var rs = this.getModifiedRecords();
            if (!rs.length) {
                return true;
            }
    
            // Next create phantoms within rs...
            for (var i = rs.length-1; i >= 0; i--) {
                if (rs[i].phantom === true) {
                    var rec = rs.splice(i, 1).shift();
                    if (rec.isValid()) {
                        try {
                            this.execute(Ext.data.Api.CREATE, rec);
                        } catch (e) {
                            this.handleException(e);
                        }
                    }
                }
                else if (!rs[i].isValid()) { // <-- while we're here, splice-off any !isValid real records
                    rs.splice(i,1);
                }
            }
            // And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
            if (rs.length) {
                for (var i = 0, len = rs.length; i < len; i++) {
                    try {
                        this.execute(Ext.data.Api.UPDATE, rs[i]);
                    }
                    catch (e) {
                        this.handleException(e);
                    }
                }
            }
            return true;
    }
        }
    //...
    Ext.data.DirectStore
    Code:
    Ext.data.DirectStore = function(c){
        Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
            proxy: (typeof(c.proxy) == 'undefined') ? new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')) : c.proxy,
            reader: (typeof(c.reader) == 'undefined' && typeof(c.fields) == 'object') ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
        }));
    };
    Ext.extend(Ext.data.DirectStore, Ext.data.Store, {
        combineUpdates: false
    });
    Ext.reg('directstore', Ext.data.DirectStore);
    Daniel Jagszent
    dɐɳiel@ʝɐgszeɳt.de <- convert to plain ASCII to get my email address

  6. #6
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Location
    Montreal
    Posts
    381
    Vote Rating
    0
    christocracy is on a distinguished road

      0  

    Default


    But I regularly use an Ext.data.GroupingStore for my Ext.Direct-enabled stores
    Right, ok. I'll find a way. I'll consider you config-param combineUpdates.
    /**
    * @author Chris Scott
    * @business www.transistorsoft.com
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    *
    * @SenchaDevs http://senchadevs.com/developers/transistor-software
    * @twitter http://twitter.com/#!/christocracy
    * @github https://github.com/christocracy
    */

Thread Participants: 2

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi