Last active
May 12, 2016 17:07
-
-
Save samselikoff/ff0d5f825a0969f82a1bc8889dba6d15 to your computer and use it in GitHub Desktop.
Example of batch/bulk operations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// mixins/batch-persist.js | |
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('You need 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); | |
} | |
}); | |
}); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// mixins/bulk-operations.js | |
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