Skip to content

Instantly share code, notes, and snippets.

@tim-evans
Created June 14, 2013 16:03
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save tim-evans/5783095 to your computer and use it in GitHub Desktop.
Save tim-evans/5783095 to your computer and use it in GitHub Desktop.
Autosave pattern for Ember with Ember Data
(function () {
// Implement debounce until backburner implements a proper debounce
var debouncees = [],
pop = Array.prototype.pop;
var debounce = function (target, method /*, args, wait */) {
var self = Ember.run.backburner,
args = arguments,
wait = pop.call(args),
debouncee,
index = -1;
// Remove debouncee
for (var i = 0, l = debouncees.length; i < l; i++) {
debouncee = debouncees[i];
if (debouncee[0] === target && debouncee[1] === method) {
index = i;
break;
}
}
if (index > -1) {
debouncees.splice(index, 1);
clearTimeout(debouncee[2]);
}
var timer = window.setTimeout(function () {
self.run.apply(self, args);
}, wait);
debouncees.push([target, method, timer]);
};
var save = function () {
if (!this.get('isSaving') &&
!this.get('isReloading')) {
this.get('content').save();
} else {
this.get('content').one('isLoaded', this, save);
}
};
Ember.Autosave = Ember.Mixin.create(/** @scope Ember.Autosave.prototype */{
/**
A list of properties that shouldn't be automatically saved.
@property manuallySavedProperties
@type String[]
@default null
*/
manuallySavedProperties: null,
/**
The number of seconds to wait for debouncing
@property wait
@type Number
@default 2000
*/
wait: 2000,
/**
Override setUnknownProperty on Em.ObjectControllers so
we can coalesce the property changes and bulk set them
when the record is ready to accept changes.
@method setUnknownProperty
@param key {String} The property being set
@param value {*} The new value of the property
*/
setUnknownProperty: function (key, value) {
var willBeManuallySaved = Em.A(this.get('manuallySavedProperties')).indexOf(key);
if (willBeManuallySaved !== -1) {
return this._super(key, value);
}
// We can't set the value yet, since
// the model is in flight.
if (this.get('isSaving') ||
this.get('isReloading')) {
if (this.__coalescedProperties__ == null) {
this.__coalescedProperties__ = {};
}
this.__coalescedProperties__[key] = value;
this.get('content').one('isLoaded', this, this.setUnknownProperty);
// The model is loaded;
// Set the new property and any coalesced properties
// set on this object
} else {
var content = this.get('content');
Ember.assert("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.".fmt(key, value, this), content);
if (this.__coalescedProperties__) {
this.__coalescedProperties__[key] = value;
content.setProperties(key, value);
this.__coalescedProperties__ = null;
} else {
content.set(key, value);
}
this.save();
}
return value;
},
/**
Save the underlying record, debouncing
with the interval defined in `wait`.
@method save
*/
save: function () {
// Try to save at least a second after a property being set
debounce(this, save, this.get('wait'));
}
});
}());
@OpakAlex
Copy link

nice +1

@DavidVotrubec
Copy link

Thanks :) +1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment