angular-restmod icon indicating copy to clipboard operation
angular-restmod copied to clipboard

issue with shared model plugin and search/fetch

Open jasonayre opened this issue 10 years ago • 7 comments

Im not sure if this is a bug or just my misusing the api heres the scenario:

Basically, what Im trying to do can be reproduced if you call search twice on a model that is using the shared_model plugin. For instance:


module.controller('ContactsIndexController', function($scope, Contact) {

  $scope.collection  = Contact.$search();
  $scope.collection = Contact.$search();

  // also for further sake of example the following yields the same results 
  // Contact.$search().$then(function(result){
  //  $scope.collection = this;
  // });
  // Contact.$search().$then(function(result){
  //  $scope.collection = this;
  // });
});

The issue is on second call of search, the shared model plugin is finding the model in cache when decoding, but then mysteriously seems to not return the actual found result back the the main collection array.

The above is not a good example but, basically the real issue Im having is, when I move to another sibling level state into my application, lets say from contacts.index to dashboard.index, then back to contacts.index, which instantiates a brand new controller, it calls contact.search again, and it wont return the actual search results since theyve been cached but for some reason, although decode is returning the result, its not being added back into the collection.

Am I missing something, or is there a better way to do the above? Or is this a bug?

jasonayre avatar Nov 08 '14 12:11 jasonayre

I believe you are experiencing the same problem as me. But I'm having the problem if I re-use a shared model in a Collection when I previously used it as a relation only. Is seems to have something to do with the $scope the object is in. The moment you create the second collection, the $scope for the model is changed from the first collection scope to the second collection scope. This seems to remove the model from the first collection.

I circumvented my problem by disabling the cache when the model is used inside a scope. But that does not work in your case.

ebuzzz avatar Nov 14 '14 14:11 ebuzzz

Yep, there is a problem with scopes and SharedModel, thats the reason why SharedModel is not officially released (I commited the file by mistake a couple of months ago).

I'm currently revising the implementation, the official plugin should be out soon.

iobaixas avatar Nov 26 '14 18:11 iobaixas

Thanks! I'll check it out when it's released. I'm using it for a couple of models in my application.

ebuzzz avatar Dec 11 '14 09:12 ebuzzz

@eborned @iobaixas

FYI: here is the semi fixed implementation Ive made. I cant remember if I fully fixed the issue or not, or whether this only solves multiple models using the plugin overriding each others data (model 1 pk = 1, model 2 pk = 1 == bad data). (I cant remember because the apps I used it on, I rearchitechted how I was loading the relations, I.E. relations were all defined on a DataStore model, which still seems pretty hacky having to do that). So I think it solves another problem entirely, but @iobaixas not sure if you solved this one yet with reworking.

/**
 * @mixin SharedModel
 *
 * @description
 *
 * Enables caching instances by primary key so a resource with a given id will always refer to the same instance.
 */

// 'use strict';

angular.module('adminfront').factory('RecordUniqueness', ['restmod', function(restmod) {
  return restmod.mixin({
    $extend : {
      Model: {
        cache: {},
      }
    }
  }, function() {

    this
        // this will cache record by its type within cache, as apparently cache
        // variable as assigned above will be shared between models
        .define('Model.$cache', function(){
          var self = this;

          if(self.cache.hasOwnProperty(self.identity())) {
            return self.cache[self.identity()];
          } else {
            return self.cache[self.identity()] = {};
          }
        })
        .define('Model.$new', function(_key, _scope) {
          var self = this;

          if(_key) {
            // search for instance with same key, if key is found then return instance
            if(self.$cache().hasOwnProperty(_key)) {
              return self.$cache()[_key];
            } else {
              return (self.$cache()[_key] = this.$super(_key, _scope));
            }
          } else {
            return this.$super(_key, _scope);
          }
        })

        // override record.$decode to update cache on decoding.
        .define('Model.$decode', function(_raw, _mask) {
          var self = this,
              result = this.$super(_raw, _mask);

          if(result.$pk) {
            self.$cache()[result.$pk] = this;
          }

          return this.$super(_raw, _mask);
        });
  });
}]);

jasonayre avatar Dec 11 '14 20:12 jasonayre

Thanks @jasonayre, didn't saw your post until now!

iobaixas avatar Feb 16 '15 20:02 iobaixas

Any news on this issue? What was your plan with the new implementation? Maybe I can help or test things out for our new application.

ebuzzz avatar Apr 28 '15 14:04 ebuzzz

Also curious on how this support is coming.

ldeboer avatar Sep 30 '15 20:09 ldeboer