Question

I would like to cache my records once they are received, but I can't figure out how. According to the Documentation you can just call this.store.push('model', record), but it doesn't seem to work. Ember requests the data from the server with each call of the route, I would like to do this only once and use the local store after it is fetched from the server.

If I try to debug it as suggested by the Documentation, i get that there is no cache:

Pd.__container__.lookup('store:main').recordCache 
// --> undefined

This is my route (where I try to cache it):

Pd.ProductsRoute = Ember.Route.extend({
    model: function () {
        var promise = this.store.find('product');
        var that = this;
        promise.then(function(value) {

            // Caching supposed to happen here
            value.content.forEach(function(product){
                that.store.push('product', product); 
            });

        }, function(reason) {
            // on rejection
        });
        return promise;
    }
});

And this the according Adapter (seems to work fine):

Pd.ProductAdapter = DS.RESTAdapter.extend({
    primaryKey: 'nid', // DOES NOT WORK BUT I CAN LIVE WITH THAT (SEE WORKAROUND)

    findAll: function(store, type) {
        var url = 'ws/rest/products';

        return new Ember.RSVP.Promise(function(resolve, reject) {

            jQuery.getJSON(url).then(function(data) {
                Ember.Logger.debug("Received Products:"); // TRIGGERS EVERY TIME!

                var srcPattern = /src=["']([^'"]+)/;

                data.forEach(function(product){
                    product.id = product.nid;
                    product.field_image = srcPattern.exec(product.field_image)[1];
                });

                Ember.Logger.debug(data);

                Ember.run(null, resolve, {product: data});
            }, function(jqXHR) {
                jqXHR.then = null; // tame jQuery's ill mannered promises
                Ember.run(null, reject, jqXHR);
            });
        });
    }
});
Was it helpful?

Solution

this.store.find('type') will always make a call to the server for records. If you only want to make a call to the server once do it in the ApplicationRoute and then instead of using find use the all filter inside of the route that's hit multiple times.

Pd.ApplicationRoute = Em.Route.extend({
  model: function(params){

    return Em.RSVP.hash({
       product: this.store.find('product'),
       somethingElse: otherPromise
    })
  }
});

Pd.ProductRoute = Em.Route.extend({
  model: function(params){
    return this.store.all('product');
  }
});

If you just want to prep the store with your products, you don't even need to return it, or use it in the app route

Pd.ApplicationRoute = Em.Route.extend({
  model: function(params){
    this.store.find('product');
    return {foo:'bar'}; // or return nothing, it doesn't matter
  }
});

Lazy loading the models

App.ProductRoute = Ember.Route.extend({
  hasPreLoaded: false,
  model: function() {
    if(this.get('hasPreLoaded')){
      return this.store.all('product');
    } else {
      this.toggleProperty('hasPreLoaded');
      return this.store.find('product');
    }
  }
});

Example

http://emberjs.jsbin.com/OxIDiVU/482/edit

You don't define the primary key on the adapter, it goes on the serializer

Pd.ProductSerializer = DS.RESTSerializer.extend({
  primaryKey: 'nid'
});

The cache no longer lives there, it lives in this.store.typeMapFor(Pd.Product) or this.store.typeMaps.

The site is still referencing an older version of ember data until ember data 1.0 is released, I'll assume you're using 1.0 beta version. This document is more up to date https://github.com/emberjs/data/blob/master/TRANSITION.md

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top