store in emberjs not loading the latest data from the server (in case of deletion at the server side)

StackOverflow https://stackoverflow.com/questions/23466639

  •  15-07-2023
  •  | 
  •  

Question

There is a /users url in my ember application. I am using RESTAdapter to fetch data from server. When a template showing list of users is loaded, it loads the latest updated data from the server (e.g. if I make changes in one of the row in users table, say changing the name of the user, I get that change reflected at front-end as well). But if I delete the user from database, I still get that user in the users' list at the front-end.

The model-hook for users route simply returns the list of users from server:

this.store.find('user').then(onSuccess, onError);

When I try to do any operation on deleted user (say updating it's name at front-end), I get an error (which is obvious as the user is no more in the database and server responds with an appropriate error). How to force emberjs to load the list of users that are present in the database and not just in local ember-data store? Also, why local ember-data store is in-sync with database for updation (and addition as well) but not for deletion?

Was it helpful?

Solution

The problem is explained at the github issue.

The store has a cache for each model type, then when the store fetch data with the _findAll method method, it does not assume that is returning all the data, so the following steps are applied

store.pushMany(type, payload); // push the server response data to the local store
store.didUpdateAll(type); // update record with the most up-to-date record     
return store.all(type);  // return all the record in the local store

It will not take in consideration any record deletion as it is discussed in the issue, in this case the new response data would be added to the local store if a record with its same primaryKey cannot be found or in the other case, it will update the local copy.

I created a test to check the defined behaviour:

test('store.findAll does not manage record deletion', function() {

$.mockjaxClear();

$.mockjax({ url: '/categories', dataType: 'json', responseText: {

 categories:[
    {id: 1, name: "Name1"},
    {id: 2, name: "Name2"}
   ]}});

var store = this.store();
stop();
store.find('category').then(function(result) {

  equal(result.get('length'), 2, 'the new item returned with ajax is added to the local store');

  $.mockjaxClear();
  $.mockjax({ url:  '/categories', dataType: 'json', responseText: {
      categories:[
          {id: 3,  name: "Name3"},
  ]}});

  store.find('category').then(function(result) {

      equal(result.get('length'), 3);

      $.mockjaxClear();
      $.mockjax({ url:  '/categories', dataType: 'json', responseText: {
          categories:[
              {id: 3,  name: "Name4"},
           ]}});

      store.find('category').then(function(result) {

          equal(result.get('length'), 3);
          equal(result.objectAt(2).get('name'), 'Name4', 'the old item returned with the new ajax request updates the local store');

          start();

      });

});

});

});

As you pointed something like find('modelName', {}) would solve your issue:

this.store.find('user', {})

OTHER TIPS

It seems that this is a known bug in Emberjs. The workaround that I found (accidently) was : supply any arbitrary parameter to find() method and the data loaded will be the same one fetched from the server. Below an example shows that xyz parameter is being passed with value abc.

this.store.find('user', {xyz:"abc"}).then(onSuccess, onError);

I am not sure if this is THE RIGHT WAY to do it, but it works for me. The other solutions would be those which are mentioned in the link (like sending some metadata from server i.e. maintaining the list of deleted records).

But I still couldn't figure out why this happens in case of DELETE only (and not in case of POST and PUT).

I am not sure if this really is a problem or I just do not understand EmberJS that much. Any help or comments on the same would be much appreciated.

To overcome this problem, you can unload all of the records from the store and then call find():

this.store.unloadAll('user');
this.store.find('user').then(
  function(d) { 
    console.log(d.get('length')); // store now only contains the users returned from the server
  }
);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top