Skip to content

Instantly share code, notes, and snippets.

@doublemarked
Last active May 2, 2016 00:40
Show Gist options
  • Save doublemarked/7658a16d0f8f6420df8e to your computer and use it in GitHub Desktop.
Save doublemarked/7658a16d0f8f6420df8e to your computer and use it in GitHub Desktop.
Boot script for fragmented loading of Loopback models

Fragmenting Loopback Models

Hey! I've bundled this approach into a component: https://github.com/doublemarked/loopback-component-model-fragments

This boot script will load module components on app initialization. Stick this file in server/boot. Components are looked for in the directory common/models/model-name. The script will load recursively any script from that directory, passing it the Model handle as a parameter (just like model.js loads). Conveniently, since this is occuring during the boot phase, those model scripts will execute at a later phase than model.js, meaning PersistedModel is already initialized and all peer model handles are already usable. Note - it's necessary for you to still maintain a model.js file for Loopback to load the model at all.

AUTHOR: Heath Morrison | @govright.org | http://github.com/doublemarked

QUESTIONS? Write me or join us on Gitter: https://gitter.im/strongloop/loopback

// AUTHOR: Heath Morrison | <firstname>@govright.org | http://github.com/doublemarked
// QUESTIONS? Write me or join us on Gitter: https://gitter.im/strongloop/loopback
//
// This boot script will load module components on app initialization. Stick this file in server/boot.
// Components are looked for in the directory common/models/model-name. The script will load recursively any
// script from that directory, passing it the Model handle as a parameter (just like model.js loads).
// Conveniently, since this is occuring during the boot phase, those model scripts will execute at a later
// phase than model.js, meaning PersistedModel is already initialized and all peer model handles are already usable.
// Note - it's necessary for you to still maintain a model.js file for Loopback to load the model at all.
module.exports = function(app) {
Object.keys(app.models).forEach(function (key) {
loadComponents(app.models[key]);
});
};
function loadComponents(Model, options) {
options = options || {};
var componentsPath = options.path || Model.settings.components || 'common/models/' + slugify(Model.modelName);
try {
recursiveRequire(appRoot + '/' + componentsPath);
} catch (e) {
// anything other than 'file not found' should be a hard fail
if (e.code !== 'ENOENT') {
console.error('Failure loading component path:', appRoot + '/' + componentsPath);
process.exit(1);
}
}
function recursiveRequire(sourcePath) {
fs.readdirSync(sourcePath).forEach(function (f) {
var filePath = sourcePath + '/' + f;
if (fs.lstatSync(filePath).isDirectory()) {
recursiveRequire(filePath);
} else if (path.extname(f) === '.js') {
require(filePath)(Model);
}
});
}
}
// Works for 99% of cases. For others, set explicit path via options/config.
function slugify(name) {
name = name.replace(/^[A-Z]+/, function (s) { return s.toLowerCase(); });
return name.replace(/[A-Z]/g, function (s) { return '-' + s.toLowerCase(); });
}

Here's an example of how one of our models (Scope) has been broken into components:

common/models/scope
common/models/scope/hooks.js
common/models/scope/linker.js
common/models/scope/methods.js
common/models/scope/overrides.js
common/models/scope/remotes
common/models/scope/remotes/find-linked.js
common/models/scope/remotes/find-one-linked.js
common/models/scope/remotes/find-parent.js
common/models/scope/validations.js
common/models/scope.js
common/models/scope.json

@drmikecrowe
Copy link

If desired, you can also split up your static methods into a

    methods/

directory as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment