From ef72efa70b59dff6199de0cd7e04d8e69f09b8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 16 Jun 2014 10:56:55 +0200 Subject: [PATCH] executor: Split model boot into two phases In the first phase, all models are defined. In the second phase, models are configured, attached to data-sources and exposed on the app object. This way when the `attached` Model event is emitted, all models are already defined and thus a listener can get reference of any other model used in the app. --- lib/executor.js | 16 ++++++++++++---- test/executor.test.js | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lib/executor.js b/lib/executor.js index 6c3d63d..b9cbcb1 100644 --- a/lib/executor.js +++ b/lib/executor.js @@ -95,6 +95,17 @@ function setupDataSources(app, instructions) { } function setupModels(app, instructions) { + defineModels(instructions); + + instructions.models.forEach(function(data) { + // Skip base models that are not exported to the app + if (!data.config) return; + + app.model(data._model, data.config); + }); +} + +function defineModels(instructions) { instructions.models.forEach(function(data) { var name = data.name; var model; @@ -122,10 +133,7 @@ function setupModels(app, instructions) { } } - // Skip base models that are not exported to the app - if (!data.config) return; - - app.model(model, data.config); + data._model = model; }); } diff --git a/test/executor.test.js b/test/executor.test.js index 80911a7..1460214 100644 --- a/test/executor.test.js +++ b/test/executor.test.js @@ -62,7 +62,6 @@ describe('executor', function() { }.toString()); boot.execute(app, someInstructions({ - dataSources: { db: { connector: 'memory' } }, models: [ { name: 'Customer', @@ -83,7 +82,6 @@ describe('executor', function() { it('defines model without attaching it', function() { boot.execute(app, someInstructions({ - dataSources: { db: { connector: 'memory' } }, models: [ { name: 'Vehicle', @@ -113,6 +111,35 @@ describe('executor', function() { assert.equal(app.models.User.dataSource, app.dataSources.theDb); }); + it('defines all models first before running the config phase', function() { + appdir.writeFileSync('models/Customer.js', 'module.exports = ' + + function(Customer/*, Base*/) { + Customer.on('attached', function() { + Customer._modelsWhenAttached = + Object.keys(Customer.modelBuilder.models); + }); + }.toString()); + + boot.execute(app, someInstructions({ + models: [ + { + name: 'Customer', + config: { dataSource: 'db' }, + definition: { name: 'Customer' }, + sourceFile: path.resolve(appdir.PATH, 'models', 'Customer.js') + }, + { + name: 'UniqueName', + config: { dataSource: 'db' }, + definition: { name: 'UniqueName' }, + sourceFile: undefined + } + ] + })); + + expect(app.models.Customer._modelsWhenAttached).to.include('UniqueName'); + }); + it('instantiates data sources', function() { boot.execute(app, dummyInstructions); assert(app.dataSources); @@ -257,7 +284,7 @@ function someInstructions(values) { var result = { app: values.app || {}, models: values.models || [], - dataSources: values.dataSources || {}, + dataSources: values.dataSources || { db: { connector: 'memory' } }, files: { boot: [] }