Opened 8 years ago

Closed 7 years ago

Last modified 7 years ago

#13445 closed defect (fixed)

Problem with the Dojo.Store.Memory

Reported by: j105rob Owned by: Kris Zyp
Priority: high Milestone: 1.8
Component: Data Version: 1.6.1
Keywords: Cc:
Blocked By: Blocking:

Description

After much testing, I may have come across an issue that might be considered a bug.

I (j105rob) am available on the IRC most days from 0600 EST, if you need any questions answered or further examples.

Here is a link to the maillist topic: http://dojo-toolkit.33424.n3.nabble.com/Dojo-1-6-Stores-interesting-findings-and-potential-Bug-td3168934.html#a3172217

Here is the original text minus the discussion I had with Ben H.:

I have an Observable store that is comprised of a Caching store that uses a JRS and a Memory store.

I am observing a query in my widget for changes to the data.

When an item is added to the store via the store.add(), it goes thru the JRS up to the server and is added to the database and the newly inserted item is returned with additional properties created at insert time. This "new" item is added to the caching store properly, but since the caching store's add() (really put() underneath) only returns the id of the item added, the observable store's observation code:

whenFinished("add", function(object){

store.notify(object);

});

implemented as:

function whenFinished(method, action){

var original = store[method]; if(original){

store[method] = function(value){

if(inMethod){

if one method calls another (like add() calling put()) we don't want two events console.log("inMethod",method,results); return original.apply(this, arguments);

} inMethod = true; try{

return dojo.when(original.apply(this, arguments), function(results){

action((typeof results == "object" && results)
value);

return results;

});

}finally{

inMethod = false;

}

};

}

}

prevents the "new" item from being returned since the results of the original.apply(this,arguments) is the id, which is not an object, but an integer, so the action((typeof results == "object" && results)
value); sends the client side item (the object that only has part of the item data, provided in this case via the "value") to the store.notify().

The problem is that I need the actual row (item) of data that is created by the insert process on the server side, not what I created on the client and passed to the server. The client side item is pretty much useless, and there is no way to get the item being send back in the response of the store.put(); if I use the current implementation of the observable store.

Change History (7)

comment:1 Changed 8 years ago by Jared Jurkiewicz

Owner: set to Kris Zyp

comment:2 Changed 8 years ago by ben hockey

fwiw, my suggestion was to fix it like this

whenFinished("add", function (id) {
  dojo.when(store.get(id), function (object) {
    store.notify(object);
  });
});

as well as something similar for whenFinished("put" ... ). the only downside is that this adds an extra store.get which could mean another call to the server. is there a way to avoid that extra request?

comment:3 Changed 8 years ago by bill

Component: GeneralData

comment:4 Changed 8 years ago by ozdev

My suggestion is:

Deferred.when(results, function(id){
   if (method == "remove"){
       action(value);
   } else {
       Deferred.when(store.get(id), function(object){
           action(object);
       });
   }
});

...because the same part of the current implementation:

Deferred.when(results, function(results){
    action((typeof results == "object" && results) || value);
});

...mistakenly assumes that store.add/put returns an object whereas the correct return value of add/put is the id of the newly created/modified object according to the Dojo Store API.

This fix adds an extra store.get call as well like the suggestion above but it's unavoidable if we stick to the current API.

Last edited 8 years ago by ozdev (previous) (diff)

comment:5 Changed 8 years ago by IIIEII

I had another problem connected with described topic.

I'm using Observable(Cache(JsonRest?, Memory)) store with new dgrid. It works great except adding new rows without id. Scenario:

  1. Add new row to store without id (server must assign it)
  2. Store sends row to server with POST and dgrid renders new row (of course it has no id)
  3. Server returns row with id and store puts it into Memory
  4. Memory's method put returns id, but observable put waits for object, that is why dgrid doesn't catch this and doesn't update row
  5. Any new update in this row throws error trying to send it to server with POST

I workarounded this with:

var MyMemory = declare([Memory], {
    put: function(object, options) {
        var id = this.inherited(arguments);
        return this.get(id);
    }
});

comment:6 Changed 7 years ago by Kris Zyp

Resolution: fixed
Status: newclosed

I believe this issue has been fixed with [27713].

comment:7 Changed 7 years ago by bill

Milestone: tbd1.8
Note: See TracTickets for help on using tickets.