offshore
Version:
An ORM for Node.js
152 lines (127 loc) • 4.67 kB
JavaScript
/**
* Aggregate Queries Adapter Normalization
*/
var _ = require('lodash');
var async = require('async');
var normalize = require('../utils/normalize');
var hasOwnProperty = require('../utils/helpers').object.hasOwnProperty;
module.exports = {
// If an optimized createEach exists, use it, otherwise use an asynchronous loop with create()
createEach: function(valuesList, cb, metaContainer) {
var self = this;
var connName,
adapter;
// Normalize Arguments
cb = normalize.callback(cb);
// Build Default Error Message
var err = 'No createEach() or create() method defined in adapter!';
var query = this._query || {};
var connName = this.connection;
// check default connection
if (connName === 'default' && query.defaultConnection) {
connName = query.defaultConnection;
}
var connection = this.query.offshore.connections[connName];
// check connection
if (!connection) {
return cb(new Error('No valid connection specified'));
}
var adapter = connection._adapter;
// check transaction
if (query.transaction && query.transaction[connName]) {
connName = query.transaction[connName];
}
// Custom user adapter behavior
if (hasOwnProperty(adapter, 'createEach')) {
return adapter.createEach(connName, this.collection, valuesList, cb, metaContainer);
}
// Default behavior
// WARNING: Not transactional! (unless your data adapter is)
var results = [];
// Find the connection to run this on
if (!hasOwnProperty(adapter, 'create')) return cb(new Error(err));
async.eachSeries(valuesList, function(values, cb) {
adapter.create(connName, self.collection, values, function(err, row) {
if (err) return cb(err);
results.push(row);
cb();
}, metaContainer);
}, function(err) {
if (err) return cb(err);
cb(null, results);
});
},
// If an optimized findOrCreateEach exists, use it, otherwise use an asynchronous loop with create()
findOrCreateEach: function(attributesToCheck, valuesList, cb, metaContainer) {
var self = this;
var connName;
var adapter;
// Normalize Arguments
cb = normalize.callback(cb);
var isObjectArray = false;
if (_.isObject(attributesToCheck[0])) {
if (attributesToCheck.length > 1 &&
attributesToCheck.length !== valuesList.length) {
return cb(new Error('findOrCreateEach: The two passed arrays have to be of the same length.'));
}
isObjectArray = true;
}
// Clone sensitive data
attributesToCheck = _.clone(attributesToCheck);
valuesList = _.clone(valuesList);
var query = this._query || {};
var connName = this.connection;
// check default connection
if (connName === 'default' && query.defaultConnection) {
connName = query.defaultConnection;
}
var connection = this.query.offshore.connections[connName];
// check connection
if (!connection) {
return cb(new Error('No valid connection specified'));
}
var adapter = connection._adapter;
// check transaction
if (query.transaction && query.transaction[connName]) {
connName = query.transaction[connName];
}
// Custom user adapter behavior
if (hasOwnProperty(adapter, 'findOrCreateEach')) {
return adapter.findOrCreateEach(connName, this.collection, valuesList, cb, metaContainer);
}
// Build a list of models
var models = [];
var i = 0;
async.eachSeries(valuesList, function(values, cb) {
if (!_.isObject(values)) return cb(new Error('findOrCreateEach: Unexpected value in valuesList.'));
// Check that each of the criteria keys match:
// build a criteria query
var criteria = {};
if (isObjectArray) {
if (_.isObject(attributesToCheck[i])) {
Object.keys(attributesToCheck[i]).forEach(function(attrName) {
criteria[attrName] = values[attrName];
});
if (attributesToCheck.length > 1) {
i++;
}
} else {
return cb(new Error('findOrCreateEach: Element ' + i + ' in attributesToCheck is not an object.'));
}
} else {
attributesToCheck.forEach(function(attrName) {
criteria[attrName] = values[attrName];
});
}
return self.findOrCreate.call(self, criteria, values, function(err, model) {
if (err) return cb(err);
// Add model to list
if (model) models.push(model);
cb(null, model);
}, metaContainer);
}, function(err) {
if (err) return cb(err);
cb(null, models);
});
}
};