如何在不在models文件夹中的情况下创建普通的sails模型

时间:2014-01-13 07:03:38

标签: javascript node.js models sails.js waterline

所以,

我正在为我的应用程序实现一个插件api,插件可以拥有自己的模型,想象一下。

SimplePlugin = {
    pluginName: 'simple',

    pluginConfig: {},

    SimpleModel: {

        attributes: {
            name: 'string'
        }

    } 

}

因此,我需要能够在需要时创建具有功能的“一次性”模型,它需要具有与其他模型完全相同的功能,因此您可以自动获取/simplePlugin/:id之类的网址{ {1}} ..等等

由于

5 个答案:

答案 0 :(得分:12)

在项目的当前状态下,你想做什么对Sails来说并不容易和有点混乱。我指的是v0.10版本。您需要做的是

  1. SimplePlugin.SimpleModel中的模型定义注入sails.models
  2. 使用_config: { rest: true }
  3. 为模型注入虚拟控制器

    请注意,我发布的代码示例来自我正在处理的自定义Sails挂钩,并假设访问sails以及在Sails初始化的loadHooks阶段执行的代码示例在MiddlewareRegistry阶段之前(比较:lib/app/load.js)。

    1。注入模型定义

    在Sails v0.10中的hints in the orm hook之后,你必须:

    • 获取api中定义的模型和适配器,将新模型合并到字典中
    • 通过sails.hooks.orm.normalizeModelDef
    • 规范化模型定义
    • 将规范化的模型定义加载到Waterline
    • 通过teardown
    • 卸载现有的适配器连接
    • 重新初始化水线
    • 通过sails.hooks.orm.prepareModels(之前:sails.hooks.orm.exposeModels,更改为:8d96895662)将已初始化的水线集合展示给风帆和全球范围

    因为您必须重新初始化Waterline并重新加载所有模型定义,我建议收集所有模型定义以进行注入并将它们传递给inject函数一次。下面的示例代码反映了这一点。

    ...
    
    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。注入控制器

    对于应通过蓝图方法公开的每个模型,您必须:

    • 创建具有匹配标识和已启用蓝图的控制器定义
    • 将控制器保存到sails.controllers[controllerId]
    • 将控制器保存到sails.hooks.controllers.middleware[controllerId]

    Sails 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);
            });
          });
        }
    
      }
    
    }
    

答案 1 :(得分:0)

编辑:完全无法正常工作,因为在初始化时会将集合分配给连接。

似乎有一个更好的解决方案,有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
});

答案 2 :(得分:0)

在v0.12 sails.hooks.orm.normalizeModelDef不再存在。此外sails/lib/hooks/orm/loadUserModules转到sails-hook-orm npm模块,不再是帆的一部分。

答案 3 :(得分:0)

试试这个: “从指定目录加载模型,控制器,服务,策略和配置,并将它们注入主Sails应用程序。”

https://github.com/leeroybrun/sails-util-mvcsloader

答案 4 :(得分:0)

惊讶的风帆在2018年不支持此功能:我继续使用叉子(@eyn答案)继续上述软件包,并提供适用于风帆v1.x.x的更新。

https://github.com/emahuni/sails-util-micro-apps

我将其更改为那个coz,我在该程序包中更改了很多东西。我不希望只加载模型和控制器来加载整个应用程序,而是用于微服务架构的微型应用程序。这样一来,您就可以使用可重复使用的api代码制作可以组合在一起以组成一个大型应用程序的微型应用程序。