diff --git a/lib/waterline/methods/find-one.js b/lib/waterline/methods/find-one.js index a68b5cec2..dbf98e26f 100644 --- a/lib/waterline/methods/find-one.js +++ b/lib/waterline/methods/find-one.js @@ -319,10 +319,19 @@ module.exports = function findOne( /* criteria?, populates?, explicitCbMaybe?, m return proceed(undefined, thePopulatedRecord); }//-• - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // FUTURE: This is where the `afterFindOne()` lifecycle callback would go - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return proceed(undefined, thePopulatedRecord); + // If no afterFindOne callback defined, just proceed. + if (!_.has(WLModel._callbacks, 'afterFindOne')) { + return proceed(undefined, thePopulatedRecord); + }//-• + + // Otherwise, run it. + return WLModel._callbacks.afterFindOne(thePopulatedRecord, function(err) { + if (err) { + return proceed(err); + } + + return proceed(undefined, thePopulatedRecord); + }); })(function _afterPotentiallyRunningAfterLC(err, thePopulatedRecord){ if (err) { return done(err); } diff --git a/lib/waterline/methods/find.js b/lib/waterline/methods/find.js index e9680daf8..140ced138 100644 --- a/lib/waterline/methods/find.js +++ b/lib/waterline/methods/find.js @@ -276,10 +276,19 @@ module.exports = function find( /* criteria?, populates?, explicitCbMaybe?, meta return proceed(undefined, populatedRecords); }//-• - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // FUTURE: This is where the `afterFind()` lifecycle callback would go - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return proceed(undefined, populatedRecords); + // If no afterFind callback defined, just proceed. + if (!_.has(WLModel._callbacks, 'afterFind')) { + return proceed(undefined, populatedRecords); + }//-• + + // Otherwise, run it. + return WLModel._callbacks.afterFind(populatedRecords, function(err) { + if (err) { + return proceed(err); + } + + return proceed(undefined, populatedRecords); + }); })(function _afterPotentiallyRunningAfterLC(err, populatedRecords) { if (err) { return done(err); } diff --git a/test/unit/callbacks/afterFind.find.js b/test/unit/callbacks/afterFind.find.js new file mode 100644 index 000000000..e0d92b086 --- /dev/null +++ b/test/unit/callbacks/afterFind.find.js @@ -0,0 +1,108 @@ +var assert = require('assert'); +var _ = require('@sailshq/lodash'); +var Waterline = require('../../../lib/waterline'); + +describe('After Find Lifecycle Callback ::', function() { + describe('Create ::', function() { + var person; + + before(function(done) { + var waterline = new Waterline(); + var Model = Waterline.Model.extend({ + identity: 'user', + datastore: 'foo', + primaryKey: 'id', + fetchRecordsOnCreate: true, + attributes: { + id: { + type: 'number' + }, + name: { + type: 'string' + } + }, + + afterFind: function(results, cb) { + results.forEach(function (record) { + record.name = record.name + ' updated'; + }); + return cb(); + } + }); + + waterline.registerModel(Model); + + // Fixture Adapter Def + var adapterDef = { find: function(con, query, cb) { return cb(null, [ + {id: 1, name: 'John Doe', criteria: query.criteria}, + {id: 2, name: 'Jane Doe', criteria: query.criteria}, + ]); }}; + + var connections = { + 'foo': { + adapter: 'foobar' + } + }; + + waterline.initialize({ adapters: { foobar: adapterDef }, datastores: connections }, function(err, orm) { + if (err) { + return done(err); + } + person = orm.collections.user; + return done(); + }); + }); + + it('should run afterFind and mutate values', function(done) { + person.find({}, {}, function(err, results) { + if (err) { + return done(err); + } + + assert(_.isArray(results)); + assert.equal(results[0].name, 'John Doe updated'); + assert.equal(results[1].name, 'Jane Doe updated'); + return done(); + }); + }); + + it('should run afterFind and mutate values when using deferreds', function(done) { + person.find() + .limit(1) + .skip(1) + .sort([{ name: 'desc' }]) + .exec(function(err, results) { + if (err) { + return done(err); + } + + assert(_.isArray(results)); + assert.equal(results[0].name, 'John Doe updated'); + assert.equal(results[0].criteria.limit, 1); + assert.equal(results[0].criteria.skip, 1); + assert.equal(results[0].criteria.sort[0].name, 'DESC'); + assert.equal(results[1].name, 'Jane Doe updated'); + + return done(); + }); + }); + + it('should not run afterFind when skipAllLifecycleCallbacks is true', function(done) { + person.find() + .meta({ + skipAllLifecycleCallbacks: true + }) + .exec(function(err, results) { + if (err) { + return done(err); + } + + assert(_.isArray(results)); + assert.equal(results[0].name, 'John Doe'); + assert.equal(results[1].name, 'Jane Doe'); + + return done(); + }); + }); + }); +}); diff --git a/test/unit/callbacks/afterFindOne.findOne.js b/test/unit/callbacks/afterFindOne.findOne.js new file mode 100644 index 000000000..a893a8047 --- /dev/null +++ b/test/unit/callbacks/afterFindOne.findOne.js @@ -0,0 +1,65 @@ +var assert = require('assert'); +var _ = require('@sailshq/lodash'); +var Waterline = require('../../../lib/waterline'); + +describe('After FindOne Lifecycle Callback on findOrCreate::', function() { + describe('Create ::', function() { + var person; + + before(function(done) { + var waterline = new Waterline(); + var Model = Waterline.Model.extend({ + identity: 'user', + datastore: 'foo', + primaryKey: 'id', + fetchRecordsOnCreate: true, + attributes: { + id: { + type: 'number' + }, + name: { + type: 'string' + } + }, + + afterFindOne: function(record, cb) { + record.name = record.name + ' updated'; + return cb(); + } + }); + + waterline.registerModel(Model); + + // Fixture Adapter Def + var adapterDef = { find: function(con, query, cb) { return cb(null, [ + {id: 1, name: 'John Doe', criteria: query.criteria}, + ]); }}; + + var connections = { + 'foo': { + adapter: 'foobar' + } + }; + + waterline.initialize({ adapters: { foobar: adapterDef }, datastores: connections }, function(err, orm) { + if (err) { + return done(err); + } + person = orm.collections.user; + return done(); + }); + }); + + it('should run afterFindOne when findOne finds a record', function(done) { + person.findOne({ id: 1 }, { }, function(err, record) { + if (err) { + return done(err); + } + + assert.equal(record.name, 'John Doe updated'); + return done(); + }); + }); + + }); +}); diff --git a/test/unit/callbacks/afterFindOne.findOrCreate.js b/test/unit/callbacks/afterFindOne.findOrCreate.js new file mode 100644 index 000000000..0e742ff66 --- /dev/null +++ b/test/unit/callbacks/afterFindOne.findOrCreate.js @@ -0,0 +1,65 @@ +var assert = require('assert'); +var _ = require('@sailshq/lodash'); +var Waterline = require('../../../lib/waterline'); + +describe('After FindOne Lifecycle Callback on findOrCreate::', function() { + describe('Create ::', function() { + var person; + + before(function(done) { + var waterline = new Waterline(); + var Model = Waterline.Model.extend({ + identity: 'user', + datastore: 'foo', + primaryKey: 'id', + fetchRecordsOnCreate: true, + attributes: { + id: { + type: 'number' + }, + name: { + type: 'string' + } + }, + + afterFindOne: function(record, cb) { + record.name = record.name + ' updated'; + return cb(); + } + }); + + waterline.registerModel(Model); + + // Fixture Adapter Def + var adapterDef = { find: function(con, query, cb) { return cb(null, [ + {id: 1, name: 'John Doe', criteria: query.criteria}, + ]); }}; + + var connections = { + 'foo': { + adapter: 'foobar' + } + }; + + waterline.initialize({ adapters: { foobar: adapterDef }, datastores: connections }, function(err, orm) { + if (err) { + return done(err); + } + person = orm.collections.user; + return done(); + }); + }); + + it('should run afterFindOne when findOrCreate finds a record', function(done) { + person.findOrCreate({ id: 1 }, { name: 'John Doe' }, function(err, record) { + if (err) { + return done(err); + } + + assert.equal(record.name, 'John Doe updated'); + return done(); + }); + }); + + }); +});