Skip to content

Instantly share code, notes, and snippets.

@samselikoff
Created April 13, 2017 03:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samselikoff/edf2bd2f46ea4ed7f5ae63dcedcf82c4 to your computer and use it in GitHub Desktop.
Save samselikoff/edf2bd2f46ea4ed7f5ae63dcedcf82c4 to your computer and use it in GitHub Desktop.
import ApplicationAdapter from './application';
import BulkOperations from 'ted-ed-lesson-creator/mixins/bulk-operations';
export default ApplicationAdapter.extend(BulkOperations, {
bulkCollectionName: 'item', // used to build the endpoint, in this case becomes /items
bulkOperations: ['PUT', 'POST']
});
import Ember from 'ember';
var queue = [];
export default Ember.Mixin.create({
/**
* Override this method to actually make your batch API call, then
* resolve/reject each request.
*/
batch: function (requests) {
throw new Error('Your model needs to implement the batch() method. See https://github.com/jayphelps/ember-model-batch/blob/master/README.md');
},
_flushQueue: function () {
var ajaxHook = this.ajax,
ajaxOriginal = this.constructor.__super__.ajax;
// Reset original ajax method so they can use it if they'd like
this.ajax = ajaxOriginal;
// Run batch with a deep copy so no side-effects if they alter it
this.batch(Ember.copy(queue, true));
// Empty the queue and add our hook back;
queue.length = 0;
this.ajax = ajaxHook;
},
ajax(...args) {
// TODO: This is suuper brittle, I believe __nextSuper changes in 2.1ish. Should
// be able to make it just _super then.
let _super = this.__nextSuper.bind(this);
return new Ember.RSVP.Promise((resolve, reject) => {
queue.push({
args: args,
resolve,
reject
});
Ember.run.later(() => {
if (!queue.length) {
return;
}
if (queue.length === 1) {
queue.length = 0;
return _super(...args).then(resolve, reject);
} else {
Ember.run.once(this, this._flushQueue);
}
});
});
}
});
import Ember from 'ember';
import BatchPersist from './batch-persist';
const { pluralize } = Ember.String;
export default Ember.Mixin.create(BatchPersist, {
bulkOperations: [],
batch(originalRequests) {
let collectionName = this.get('bulkCollectionName');
let groupedRequests = originalRequests.reduce((memo, request) => {
let type = request.args[1];
memo[type].push(request);
return memo;
}, {GET: [], POST: [], PUT: [], PATCH: [], 'DELETE': []});
let finalRequests = Object.keys(groupedRequests).reduce((memo, method) => {
let requests = groupedRequests[method];
if (!requests.length) {
return memo;
}
if ((this.get('bulkOperations').indexOf(method) > -1) && (requests.length > 1)) {
let payload = requests
.map(req => {
let attrs = req.args[2].data[collectionName];
if (method === 'PUT') {
/*
This is really ugly, have to get the `id` from the model's original PUT url
*/
let path = req.args[0];
let id = path.substr(path.lastIndexOf('/') + 1);
attrs.id = id;
}
return attrs;
});
let url = this.buildURL(collectionName);
let data = JSON.stringify({ [pluralize(collectionName)]: payload });
return [...memo, this._bulkRequest(method, url, data, requests)];
} else {
return memo.concat(requests
.map(request => {
let data = (request.args[2] && request.args[2].data) ? request.args[2].data : null;
return Ember.$.ajax({
type: request.args[1],
url: request.args[0],
data: data ? JSON.stringify(data) : undefined,
headers: {
'Content-Type': 'application/json'
}
}).then(request.resolve, request.reject);
})
);
}
}, []);
return finalRequests;
},
_bulkRequest(type, url, data, originalRequests) {
return Ember.$.ajax({
type,
url,
data,
headers: {
'Content-Type': 'application/json'
}
})
.then((payload) => {
let bulkRoot = Object.keys(JSON.parse(data))[0];
let resolvedRecords = payload[bulkRoot];
let singularRoot = bulkRoot.singularize();
return originalRequests.map((req, i) => {
return req.resolve({[singularRoot]: resolvedRecords[i]});
});
})
.fail(() => {
return originalRequests.map(req => req.reject());
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment