Hi,
I want my app to work online and offline, if I am online I want to persist data on rest server, if offline to local storage. So for the same model can I change adapter based on online/offline mode during runtime?
Hi,
I want my app to work online and offline, if I am online I want to persist data on rest server, if offline to local storage. So for the same model can I change adapter based on online/offline mode during runtime?
Quick idea: it would be possible to use a switching adapter, using the strategy pattern to persist to either online/offline depending on connection state.
REST or Json adapter has a ajax() method used for all API calls and it is provided with the context. You can extend an adapter and override that method.
I’m not really sure of a way that doesn’t use private APIs.
Setting the adapter is easy, store.set('adapter', 'offline');
. However, ember-data internally caching the adapter instances so it doesn’t have to try and resolve them in the future. That happens here https://github.com/emberjs/data/blob/v2.2.1/packages/ember-data/lib/system/store.js#L2010 which stores it in the _instanceCache
. You would need to flush that, and I’m unsure if there is a public API for that.
Perhaps you might have an easier time extending the rest/json adapter to be aware of offline vs online versus changing the adapter instance itself.
Yep, this is why it must be a single instance, and why I was suggesting the strategy pattern. I don’t really have time to build a full implementation, but the idea would be along those lines:
extend a basic adapter.
in its init
, have it create the two adapters, for offline and online storage. Something like this:
this._adapters = {
online: this.container.lookup('adapter:-json-api'),
offline: this.container.lookup('adapter:-local-storage')
};
(-local-storage
is not part of ember-data, you still have to do it yourself, or find one in npm).
Add a method to select current strategy:
setMode: function (mode) {
this._current = this._adapters[mode];
}
I guess you could just have a mode
property and an observer, but for something like this, I like the ceremony of calling a function.
Make all methods of your adapter forward to this._current
. Either statically:
createRecord: function(...args) { return this._current.createRecord(...args); }
Or if you want to go fancy you could make a forward generator:
function forward(name) {
return function (...args) {
return this._current[name](...args);
}
}
// In the adapter:
createRecord: forward('createRecord'),
deleteRecord: forward('deleteRecord'),
…
If you are serious about providing seamless continuity between offline and online mode, you should probably trigger some syncing between local and remote data when setMode('online')
is called.