ember-cli-copyable
Version:
Deeply copies your records including their relations. The mixin is smart enough to resolve not loaded relations and is configurable to what should be shallow/deeply copied or excluded entirely.
136 lines (108 loc) • 3.58 kB
JavaScript
import Ember from 'ember';
import DS from 'ember-data';
export default Ember.Mixin.create({
copyable: true,
copy: function(options) {
options = options || {};
var _this = this;
return new Ember.RSVP.Promise(function(resolve) {
var model = _this.constructor;
var copy = _this.get('store').createRecord(model.modelName || model.typeKey);
var queue = [];
model.eachAttribute(function(attr) {
switch(Ember.typeOf(options[attr])) {
case 'undefined':
copy.set(attr, _this.get(attr));
break;
case 'null':
copy.set(attr, null);
break;
default:
copy.set(attr, options[attr]);
}
});
model.eachRelationship(function(relName, meta) {
var rel = _this.get(relName);
if (!rel) { return; }
var overwrite;
var passedOptions = {};
switch(Ember.typeOf(options[relName])) {
case 'null':
return;
case 'instance':
overwrite = options[relName];
break;
case 'object':
passedOptions = options[relName];
break;
case 'array':
overwrite = options[relName];
break;
default:
}
if (rel.constructor === DS.PromiseObject) {
queue.push(rel.then(function(obj) {
if (obj && obj.get('copyable')) {
return obj.copy(passedOptions).then(function(objCopy) {
copy.set(relName, overwrite || objCopy);
});
} else {
copy.set(relName, overwrite || obj);
}
}));
} else if (rel.constructor === DS.PromiseManyArray) {
if (overwrite) {
copy.get(relName).pushObjects(overwrite);
} else {
queue.push(rel.then(function(array) {
var resolvedCopies =
array.map(function(obj) {
if (obj.get('copyable')) {
return obj.copy(passedOptions);
} else {
return obj;
}
});
return Ember.RSVP.all(resolvedCopies).then(function(copies){
copy.get(relName).pushObjects(copies);
});
}));
}
} else {
if (meta.kind === 'belongsTo') {
var obj = rel;
if (obj && obj.get('copyable')) {
queue.push( obj.copy(passedOptions).then(function(objCopy) {
copy.set(relName, overwrite || objCopy);
}));
} else {
copy.set(relName, overwrite || obj);
}
} else {
var objs = rel;
if (objs.get('content')) {
objs = objs.get('content').compact();
}
if (objs.get('firstObject.copyable')) {
var copies = objs.map(function(obj) {
return obj.copy(passedOptions);
});
if (overwrite) {
copy.get(relName).pushObjects(overwrite);
} else {
queue.push( Ember.RSVP.all(copies).then( function(resolvedCopies) {
copy.get(relName).pushObjects(resolvedCopies);
}));
}
} else {
copy.get(relName).pushObjects(overwrite || objs);
}
}
}
});
Ember.RSVP.all(queue).then(function() {
resolve(copy);
});
});
}
});