So,
I'm in the middle of implementing a plugin api for my application, and the plugins can have their own models, imagine this.
SimplePlugin = {
pluginName: 'simple',
pluginConfig: {},
SimpleModel: {
attributes: {
name: 'string'
}
}
}
So I need to be able to create the "one-time" model with a function whenever it's needed, it needs to have exactly the same functionality as other models so you automatically get the urls like /simplePlugin/:id
for find
..etc
Thanks
What are you trying to do is not easy and a bit messy with Sails in the current state of the project. I'm referring to the v0.10 version. What you'll have to do is
SimplePlugin.SimpleModel
into sails.models_config: { rest: true }
Please note that the code examples I posted are taken from a custom Sails hook I am working on and assume access to sails
and the code examples to be executed during the loadHooks
phase of Sails initialization / before the MiddlewareRegistry
phase (compare: lib/app/load.js).
Following the hints in the orm
hook in Sails v0.10 you have to:
api
, merge your new model into the dictionarysails.hooks.orm.normalizeModelDef
teardown
sails.hooks.orm.prepareModels
(previously: sails.hooks.orm.exposeModels
, changed with: 8d96895662)Because you have to reinitialize Waterline and reload all model definitions I'd recommend to collect all model definitions to inject and pass them to the inject function once. The example code below reflects this.
...
function injectPluginModels(pluginModels, cb) {
// copy sails/lib/hooks/orm/loadUserModules to make it accessible here
var loadUserModelsAndAdapters = require('./loadUserModules')(sails);
async.auto({
// 1. load api/models, api/adapters
_loadModules: loadUserModelsAndAdapters,
// 2. Merge additional models, 3. normalize model definitions
modelDefs: ['_loadModules', function(next){
_.each(additionModels, function(aditionModel) {
_.merge(sails.models, additionalModel);
});
_.each(sails.models, sails.hooks.orm.normalizeModelDef);
next(null, sails.models);
}],
// 4. Load models into waterline, 5. tear down connections, 6. reinitialize waterline
instantiatedCollections: ['modelDefs', function(next, stack){
var modelDefs = stack.modelDefs;
var waterline = new Waterline();
_.each(modelDefs, function(modelDef, modelID){
waterline.loadCollection(Waterline.Collection.extend(modelDef));
});
var connections = {};
_.each(sails.adapters, function(adapter, adapterKey) {
_.each(sails.config.connections, function(connection, connectionKey) {
if (adapterKey !== connection.adapter) return;
connections[connectionKey] = connection;
});
});
var toTearDown = [];
_.each(connections, function(connection, connectionKey) {
toTearDown.push({ adapter: connection.adapter, connection: connectionKey });
});
async.each(toTearDown, function(tear, callback) {
sails.adapters[tear.adapter].teardown(tear.connection, callback);
}, function(){
waterline.initialize({
adapters: sails.adapters,
connections: connections
}, next)
});
}],
// 7. Expose initialized models to global scope and sails
_prepareModels: ['instantiatedCollections', sails.hooks.orm.prepareModels]
}, cb);
};
...
Would allow you to:
// Read your plugins
...
var pluginModels = // Get all the plugin models
injectPluginModels(pluginModels, function(){
// Plugin models now available via global[pluginModel.globalId] and sails.models[pluginModel.identity]
});
For each model that should be exposed via blueprint methods you have to:
sails.controllers[controllerId]
sails.hooks.controllers.middleware[controllerId]
The Sails MiddlewareRegistry
will automatically pick up the controllers found in these objects.
function mountBlueprintsForModels(pluginModels) {
_.each(pluginModels, function(pluginModel){
var controller = _.cloneDeep(pluginModel);
controller._config = { rest: true };
var controllerId = pluginModel.identity;
if (!_.isObject(sails.controllers[controllerId])) {
sails.controllers[controllerId] = controller;
}
if (!_.isObject(sails.hooks.controllers.middleware[controllerId])) {
sails.hooks.controllers.middleware[controllerId] = controller;
}
});
}
// E.g. in /api/hooks/plugins/index.js
/*
* Module dependencies
*/
var async = require('async'),
_ = require('lodash'),
waterline = require('waterline');
module.exports = function(sails) {
// injectPluginModels and mountBlueprintsForModels defined here
...
return {
initialize: function(cb) {
sails.after('hook:orm:loaded', function() {
yourNiftyPluginLoader(function(err, plugins) {
// assuming plugin.models holds array of models for this plugin
// customize for your use case
var pluginModels = _.pluck(plugins, 'models');
injectPluginModels(pluginModels, cb);
mountBlueprintsForModels(pluginModels);
});
});
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With