diff --git a/lib/dao.js b/lib/dao.js index 61303dc0..93b49c3a 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -1821,7 +1821,7 @@ DataAccessObject.find = function find(query, options, cb) { } function queryGeo(query) { - function geoCallback(err, data) { + function geoCallbackWithoutNotify(err, data) { var memory = new Memory(); var modelName = self.modelName; @@ -1847,6 +1847,29 @@ DataAccessObject.find = function find(query, options, cb) { } } + function geoCallbackWithNotify(err, data) { + if (err) return cb(err); + + async.map(data, function(item, next) { + var context = { + Model: self, + data: item, + isNewInstance: false, + hookState: hookState, + options: options, + }; + + self.notifyObserversOf('loaded', context, function(err) { + if (err) return next(err); + next(null, context.data); + }); + }, function(err, results) { + if (err) return cb(err); + geoCallbackWithoutNotify(null, results); + }); + } + + var geoCallback = options.notify === false ? geoCallbackWithoutNotify : geoCallbackWithNotify; if (connector.all.length === 4) { connector.all(self.modelName, {}, options, geoCallback); } else { diff --git a/test/persistence-hooks.suite.js b/test/persistence-hooks.suite.js index dab7ff57..81674a6d 100644 --- a/test/persistence-hooks.suite.js +++ b/test/persistence-hooks.suite.js @@ -6,10 +6,12 @@ 'use strict'; var ValidationError = require('../').ValidationError; +var async = require('async'); var contextTestHelpers = require('./helpers/context-test-helpers'); var ContextRecorder = contextTestHelpers.ContextRecorder; var deepCloneToObject = contextTestHelpers.deepCloneToObject; var aCtxForModel = contextTestHelpers.aCtxForModel; +var GeoPoint = require('../lib/geo.js').GeoPoint; var uid = require('./helpers/uid-generator'); var getLastGeneratedUid = uid.last; @@ -24,7 +26,7 @@ module.exports = function(dataSource, should, connectorCapabilities) { } describe('Persistence hooks', function() { var ctxRecorder, hookMonitor, expectedError; - var TestModel, existingInstance; + var TestModel, existingInstance, GeoModel; var migrated = false; var undefinedValue = undefined; @@ -41,12 +43,25 @@ module.exports = function(dataSource, should, connectorCapabilities) { extra: {type: String, required: false}, }); + GeoModel = dataSource.createModel('GeoModel', { + id: {type: String, id: true}, + name: {type: String, required: false}, + location: {type: GeoPoint, required: false}, + }); + uid.reset(); if (migrated) { - TestModel.deleteAll(done); + async.series([ + function(cb) { + TestModel.deleteAll(cb); + }, + function(cb) { + GeoModel.deleteAll(cb); + }, + ], done); } else { - dataSource.automigrate(TestModel.modelName, function(err) { + dataSource.automigrate([TestModel.modelName, 'GeoModel'], function(err) { migrated = true; done(err); }); @@ -64,7 +79,12 @@ module.exports = function(dataSource, should, connectorCapabilities) { TestModel.create({name: 'second'}, function(err) { if (err) return done(err); - done(); + var location1 = new GeoPoint({lat: 10.2, lng: 6.7}); + GeoModel.create([ + {name: 'Rome', location: location1}, + ], function(err) { + done(err); + }); }); }); }); @@ -100,13 +120,51 @@ module.exports = function(dataSource, should, connectorCapabilities) { }); it('triggers correct hooks when near filter is used', function(done) { - monitorHookExecution(); + var hookMonitorGeoModel; + hookMonitorGeoModel = new HookMonitor({includeModelName: false}); + + function monitorHookExecutionGeoModel(hookNames) { + hookMonitorGeoModel.install(GeoModel, hookNames); + } + + monitorHookExecutionGeoModel(); + var query = { - where: {location: {near: '10,20', maxDistance: '10', unit: 'meters'}}, + where: {location: {near: '10,5'}}, }; - TestModel.find(query, function(err, list) { + GeoModel.find(query, function(err, list) { if (err) return done(err); - hookMonitor.names.should.eql(['access']); + hookMonitorGeoModel.names.should.eql(['access', 'loaded']); + done(); + }); + }); + + it('applies updates from `loaded` hook when near filter is used', function(done) { + GeoModel.observe('loaded', function(ctx, next) { + ctx.data.name = 'Berlin'; + next(); + }); + + var query = { + where: {location: {near: '10,5'}}, + }; + + GeoModel.find(query, function(err, list) { + if (err) return done(err); + list.map(get('name')).should.eql(['Berlin']); + done(); + }); + }); + + it('applies updates from `loaded` hook when near filter is not used', function(done) { + TestModel.observe('loaded', function(ctx, next) { + ctx.data.name = 'Paris'; + next(); + }); + + TestModel.find(function(err, list) { + if (err) return done(err); + list.map(get('name')).should.eql(['Paris', 'Paris']); done(); }); });