Skip to content

Instantly share code, notes, and snippets.

@bencolon
Created September 29, 2014 13:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bencolon/7f062cb28d7b82cd2038 to your computer and use it in GitHub Desktop.
Save bencolon/7f062cb28d7b82cd2038 to your computer and use it in GitHub Desktop.
Ember Data "find" methods with cache option
DS.Store.reopen({
/*
Examples :
this.store.findAllCached("user", { for: moment.duration(1, "hours") });
this.store.findAllCached("user", { until: moment().add(1, "hours") });
*/
findAllCached: function(type, options) {
Ember.assert("You need to pass a type to the store's findAllAndCache method", arguments.length >= 1);
Ember.assert("You need to pass a TTL option to the findAllAndCache method (`for` or `until`)",
arguments.length > 1 && (options.for || options.until));
var expiration = this._setExpirationFromOptions(options);
return this._getAllRecords(type, expiration);
},
/*
Examples :
this.store.findQueryCached("post", { filter: "active" }, { for: moment.duration(1, "hours") });
this.store.findQueryCached("post", { filter: "active" }, { until: moment().add(1, "hours") });
*/
findQueryCached: function(type, query, options) {
Ember.assert("You need to pass a type and a query to the store's findQueryCached method", arguments.length >= 2);
Ember.assert("You need to pass a query object to the findQueryCached method (`for` or `until`)",
arguments.length > 1 && Ember.typeOf(query) === "object");
Ember.assert("You need to pass a TTL option to the findQueryCached method (`for` or `until`)",
arguments.length > 2 && (options.for || options.until));
if ($.isEmptyObject(query)) {
return this.findAllCached(type, options);
}
var expiration = this._setExpirationFromOptions(options);
return this._getQueryRecords(type, query, expiration);
},
/* private methods */
_getAllRecords: function(type, expiration) {
var meta = this.metadataFor(type);
if(!meta.expiration || this._cacheExpired(meta)) {
Ember.Logger.log("Requested all %@s".fmt(type));
this.metaForType(type, { expiration: expiration });
return this.findAll(type);
} else {
Ember.Logger.log("Got all %@s from store until %@ (in %@)".fmt(type, expiration.format(), this._cacheDurationToGo(expiration)));
return DS.PromiseArray.create({
promise: Ember.RSVP.Promise.cast(this.all(type))
});
}
},
_getQueryRecords: function(type, query, expiration) {
var meta = this.metadataFor(type);
var queryStr = this._queryToString(query);
var caches = meta.caches || {};
if(!caches[queryStr] || (caches[queryStr] && this._cacheExpired(caches[queryStr]))) {
Ember.Logger.log("Requested %@s (%@)".fmt(type, queryStr));
return this._cachedPromise(type, query, expiration);
} else {
Ember.Logger.log("Got all %@s (%@) from store until %@ (in %@)".fmt(type, queryStr, expiration.format(), this._cacheDurationToGo(expiration)));
return this.metadataFor(type).caches[queryStr].promise;
}
},
_setExpirationFromOptions: function(options) {
if (options.until) {
//TODO : Ember.assert options.until format
return options.until;
} else if (options.for)
{
//TODO : Ember.assert options.for format
return moment().add(options.for);
}
},
_cacheExpired: function(meta) {
return meta.expiration && moment().isAfter(meta.expiration);
},
_cacheDurationToGo: function(expiration) {
return moment.duration(expiration.diff(moment())).humanize();
},
_cachedPromise: function(type, query, expiration) {
var queryStr = this._queryToString(query);
var promise = this.findQuery(type, query);
var caches = this.metadataFor(type).caches || {};
caches[queryStr] = { expiration: expiration, promise: promise };
this.metaForType(type, { caches: caches });
return promise;
},
_queryToString: function(query) {
return Ember.inspect(query).replace(/\W/g,'_').camelize();
},
didSaveRecord: function(record, data) {
var type = record.get("constructor.typeKey").decamelize();
this.metaForType(type, { expiration: null, caches: {} });
Ember.Logger.log("Cleaned caches for %@s".fmt(type));
this._super(record, data);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment