Как создать нормальную модель sails, не находясь в папке models
и
Я в середине реализации плагина api для моего приложения, и плагины могут иметь свои собственные модели, представьте себе это.
SimplePlugin = {
pluginName: 'simple',
pluginConfig: {},
SimpleModel: {
attributes: {
name: 'string'
}
}
}
поэтому мне нужно иметь возможность создавать "одноразовую" модель с функцией, когда это необходимо, она должна иметь точно такую же функциональность, как и другие модели, чтобы вы автоматически получали URL-адреса, такие как /simplePlugin/:id
на find
..и т. д.
спасибо
5 ответов
то, что вы пытаетесь сделать, нелегко и немного грязно с парусами в текущем состоянии проекта. Я имею в виду версии v0.10 версии. Тебе придется сделать вот что!--19-->
- введите определение модели, найденное в
SimplePlugin.SimpleModel
в паруса.модели - впрысните фиктивный регулятор для модели с
_config: { rest: true }
обратите внимание, что примеры кода, которые я опубликовал, взяты из пользовательского крючка парусов, над которым я работаю, и предполагают доступ к sails
и примеры кода, которые будут выполняться во время loadHooks
фаза инициализации парусов / перед MiddlewareRegistry
этап (сравните: lib / app / load.js).
1. Inject Model definition
после подсказки в orm
крючком в парусах v0.10 вы должны:
- получить модели и адаптеры, определенные в
api
, объединить новую модель в словарь - нормализовать определения моделей с помощью
sails.hooks.orm.normalizeModelDef
- загрузите нормализованные определения моделей в Waterline
- выгрузить exisisting подключения адаптера через
teardown
- Повторно Инициализировать Ватерлинию
- подвергните инициализированные коллекции ватерлинии парусам и глобальной области через
sails.hooks.orm.prepareModels
(ранее:sails.hooks.orm.exposeModels
, изменилась с: 8d96895662)
потому что вам нужно повторно инициализировать ватерлинию и перезагрузить все определения моделей, которые я бы рекомендовал собрать все модельные определения, котор нужно впрыснуть и передать их к впрыскивают функцию раз. Пример кода ниже отражает это.
...
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);
};
...
позволит вам:
// 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]
});
2. Inject controller
для каждой модели, которая должна быть представлена с помощью методов blueprint, вы должны:
- создайте определение контроллера с соответствующим идентификатором и включенными чертежами
- сохранить контроллер
sails.controllers[controllerId]
- сохранить контроллер
sails.hooks.controllers.middleware[controllerId]
Парус MiddlewareRegistry
автоматически подберет контроллеры, найденные в этих объектах.
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;
}
});
}
3. В действии
// 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);
});
});
}
}
}
EDIT: не работает полностью, так как коллекции назначаются соединениям при инициализации.
Кажется, что есть лучшее решение, с 3 строками кода и без отключения / повторного подключения баз данных. Я только что изучил исходный код Waterline (см.https://github.com/balderdashy/waterline/blob/master/lib/waterline.js#L109). Можно сделать что-то вроде:
var Waterline = require('waterline');
// Other dependencies
var Schema = require('waterline-schema');
var CollectionLoader = require('waterline/lib/waterline/collection/loader');
var orm = new Waterline();
var config = {
// Setup Adapters
// Creates named adapters that have have been required
adapters: {
'default': 'mongo',
mongo: require('sails-mongo')
},
// Build Connections Config
// Setup connections using the named adapter configs
connections: {
'default': {
adapter: 'mongo',
url: 'mongodb://localhost:27017/sausage'
}
}
};
orm.initialize(config, function(err, data) {
if (err) {
throw err;
}
// ORM initialized, let's add another model dynamically
var User = Waterline.Collection.extend({
identity: 'user',
connection: 'default',
attributes: {
first_name: 'string',
last_name: 'string'
}
});
orm.loadCollection(User);
var defaults = config.defaults || {};
// This is where the magic happens
var loader = new CollectionLoader(User, orm.connections, defaults);
var collection = loader.initialize(orm);
orm.collections[collection.identity.toLowerCase()] = collection;
// Done! You can now use orm.collections.user :-D
});
В v0.12 sails.hooks.orm.normalizeModelDef
больше не существует. Также sails/lib/hooks/orm/loadUserModules
пошел к sails-hook-orm
модуль npm и больше не является частью парусов.
попробуйте это: "Загрузите модели, контроллеры, службы, политики и конфигурацию из указанных каталогов и вставьте их в основное приложение Sails."
surprised sails не поддерживает это в 2018 году: я продолжил вышеуказанный пакет с вилкой (@eyn answer) с обновлениями, которые работают для sails v1.х.х.
https://github.com/emahuni/sails-util-micro-apps
Я изменил его, потому что я меняю много вещей в этом пакете. Вместо загрузки только моделей и контроллеров я хочу, чтобы он загружал целые приложения, мини-приложения для архитектуры микро-сервиса в sails. Это то, что ты можешь сделать. мини-приложения, которые можно объединить в одно большое приложение из многоразового кода API.