首页 文章

Sails REST API和MySQL:TypeError:Model.create(...) . meta不是函数

提问于
浏览
0

我正在尝试在Ubuntu 16.04数字海洋VPS上设置REST API . 我遇到了这个错误'TypeError:Model.create(...) . meta不是一个函数' . 在检查堆栈跟踪(下面发布)后,该功能实际上就在那里 .

A couple of things to note:

1)我已经成功地做了一个'sails lift'命令,它确实创建了'testauthdb'及其相关的模式(如下所示)

2)使用邮递员(如下所示),我能够成功点击我的远程服务器上的API,但它返回了500错误的堆栈跟踪(如下所示) .

3)我尝试了几种更新所有软件包(@beta,@ rootst),npm缓存清理,重新安装node_modules,nginx服务器重启,完全删除项目和重新安装,启动升级命令等的方法 .

4)https://github.com/balderdashy/sails/issues/4177,是一个类似的问题,但他们使用的是mongodb和mongoose . 我尝试使用sails-mysql @ beta和sails-mysql @ latest,没有运气 .

5)编译器没有捕获语法错误,因此您可能会在本文档中看到任何可能出现翻译问题的小错误 . 我认为唯一真正的错误是 Headers /堆栈跟踪中发布的错误 .

任何指导都会非常感激,我花了很多时间试图解决这个问题 .

版本节点-v:9.10.1 npm -v:5.8.0 sails -v:1.0.0

package.json

{
  "name": "blah",
  "private": true,
  "version": "0.0.0",
  "description": "a Sails application",
  "keywords": [],
  "dependencies": {
    "@sailshq/connect-redis": "^3.2.1",
    "@sailshq/lodash": "^3.10.2",
    "@sailshq/socket.io-redis": "^5.2.0",
    "@sailshq/upgrade": "^1.0.9",
    "ajv": "^6.4.0",
    "async": "^2.6.0",
    "bcryptjs": "^2.4.3",
    "coffeescript": "^2.2.4",
    "grunt": "1.0.1",
    "jsonwebtoken": "^8.2.0",
    "lodash": "^4.17.5",
    "sails": "^1.0.0",
    "sails-hook-grunt": "^3.0.2",
    "sails-hook-orm": "^2.0.0",
    "sails-hook-sockets": "^1.5.2",
    "sails-hook-validation": "^0.4.7",
    "sails-mysql": "^1.0.0",
    "sprint-js": "^0.1.0",
    "waterline": "^0.13.3"
  },
  "devDependencies": {
    "@sailshq/eslint": "^4.19.3"
  },
  "scripts": {
    "start": "NODE_ENV=production node app.js",
    "test": "npm run lint && npm run custom-tests && echo 'Done.'",
    "lint": "eslint . --max-warnings=0 --report-unused-disable-directives && echo '✔  Your .js files look good.'",
    "custom-tests": "echo \"(No other custom tests yet.)\" && echo"
  },
  "main": "app.js",
  "repository": {
    "type": "git",
    "url": "git://github.com/root/dwms-api.git"
  },
  "author": "root",
  "license": "",
  "engines": {
    "node": ">=9.10"
  }
}

api/controller/UserController.js

var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");

module.exports = {
  /**
   * this is used to authenticate user to our api using either email and password
   * POST /login
   * @param req
   * @param res
   */
  login: function (req, res) {

    /**
     * this is param checking if they are provided
     */
    if (!_.has(req.body, 'email') || !_.has(req.body, 'password')) {
      return res.serverError("No field should be empty.");
    }

    /**
     * check if the username matches any email or phoneNumber
     */
    User.findOne({
      email: req.body.email
    }).exec(function callback(err, user) {
      if (err) return res.serverError(err);

      if (!user) return res.serverError("User not found, please sign up.");


      //check password
      bcrypt.compare(req.body.password, user.password, function (error, matched) {
        if (error) return res.serverError(error);

        if (!matched) return res.serverError("Invalid password.");

        //save the date the token was generated for already inside toJSON()

        var token = jwt.sign(user.toJSON(), "this is my secret key", {
          expiresIn: '10m'
        });

        //return the token here
        res.ok(token);
      });

    });
  },

  /**
   * this is used to request for another token when the other token is about
   * expiring so for next request call the token can be validated as true
   * GET /token
   * @param req
   * @param res
   */
  token: function (req, res) {
    User.findOne(req.user.id).exec(function callback(error, user) {
      if (error) return res.serverError(error);
      if (!user) return res.serverError("User not found");

      var token = jwt.sign(user.toJSON(), "this is my secret key", {
        expiresIn: '10m'
      });
        res.ok(token);
      });
    }
};

api/models/Users.js

var bcrypt = require("bcryptjs");

module.exports = {

  attributes: {
    name: {
      type: 'string',
      required: true
    },
    roles: {
      type: 'string',
      defaultsTo: "DEFAULT_USER"
          },
    email: {
      type: 'string',
      unique: true,
      required: true
    },
    password: {
      type: 'string',
      required: true
    },
    lastlogout: {
      type:'string'
    },
  },

   //attributes methods
  customToJSON: function() {
     return _.omit(this, ['password'])
    },

  /**
   * this holds our validation message by
   * sails-hook-validation dependency
   */
  validationMessages: { //hand for i18n & l10n
    names: {
      required: 'Name is required'
    },
    email: {
      email: 'Provide valid email address',
      required: 'Email is required',
      unique: 'This email is already existing'
    },
    password: {
      required: 'Password is required'
    }
  },

  /**
   * this is called so we can create our password hash for us
   *
   * before saving
   * @param values
   * @param cb
   */
  beforeCreate: function(user, cb){
    bcrypt.genSalt(10, function(err, salt){
      bcrypt.hash(user.password, salt, null, function(err, hash){
        if(err) return cb(err);
        user.password = hash;
        return cb();
      });
    });
  }
};

config/model.js

module.exports.models = {
  /***************************************************************************
  *                                                                          *
  * Your app's default connection. i.e. the name of one of your app's        *
  * connections (see `config/connections.js`)                                *
  *                                                                          *
  ***************************************************************************/

  /***************************************************************************
  *                                                                          *
  * Whether the `.create()` and `.update()` model methods should ignore      *
  * (and refuse to persist) unrecognized data-- i.e. properties other than   *
  * those explicitly defined by attributes in the model definition.          *
  *                                                                          *
  * To ease future maintenance of your code base, it is usually a good idea  *
  * to set this to `true`.                                                   *
  *                                                                          *
  * > Note that `schema: false` is not supported by every database.          *
  * > For example, if you are using a SQL database, then relevant models     *
  * > are always effectively `schema: true`.  And if no `schema` setting is  *
  * > provided whatsoever, the behavior is left up to the database adapter.  *
  * >                                                                        *
  * > For more info, see:                                                    *
  * > https://sailsjs.com/docs/concepts/orm/model-settings#?schema           *
  *                                                                          *
  ***************************************************************************/

   schema: true,


  /***************************************************************************
  *                                                                          *
  * How and whether Sails will attempt to automatically rebuild the          *
  * tables/collections/etc. in your schema.                                  *
  *                                                                          *
  * > Note that, when running in a production environment, this will be      *
  * > automatically set to `migrate: 'safe'`, no matter what you configure   *
  * > here.  This is a failsafe to prevent Sails from accidentally running   *
  * > auto-migrations on your production database.                           *
  * >                                                                        *
  * > For more info, see:                                                    *
  * > https://sailsjs.com/docs/concepts/orm/model-settings#?migrate          *
  *                                                                          *
  ***************************************************************************/

   migrate: 'alter',


  /***************************************************************************
  *                                                                          *
  * Base attributes that are included in all of your models by default.      *
  * By convention, this is your primary key attribute (`id`), as well as two *
  * other timestamp attributes for tracking when records were last created   *
  * or updated.                                                              *
  *                                                                          *
  * > For more info, see:                                                    *
  * > https://sailsjs.com/docs/concepts/orm/model-settings#?attributes       *
  *                                                                          *
  ***************************************************************************/

  attributes: {
    id: { type: 'number', autoIncrement: true, },
    createdAt: { type: 'string', autoCreatedAt: true, },
    updatedAt: { type: 'string', autoUpdatedAt: true, },
  },


  /******************************************************************************
  *                                                                             *
  * The set of DEKs (data encryption keys) for at-rest encryption.              *
  * i.e. when encrypting/decrypting data for attributes with `encrypt: true`.   *
  *                                                                             *
  * > The `default` DEK is used for all new encryptions, but multiple DEKs      *
  * > can be configured to allow for key rotation.  In production, be sure to   *
  * > manage these keys like you would any other sensitive credential.          *
  *                                                                             *
  * > For more info, see:                                                       *
  * > https://sailsjs.com/docs/concepts/orm/model-settings#?dataEncryptionKeys  *
  *                                                                             *
  ******************************************************************************/

  dataEncryptionKeys: {
    default: 'blahblah'
  },


  /***************************************************************************
  *                                                                          *
  * Whether or not implicit records for associations should be cleaned up    *
  * automatically using the built-in polyfill.  This is especially useful    *
  * during development with sails-disk.                                      *
  *                                                                          *
  * Depending on which databases you're using, you may want to disable this  *
  * polyfill in your production environment.                                 *
  *                                                                          *
  * (For production configuration, see `config/env/production.js`.)          *
  *                                                                          *
  ***************************************************************************/

  cascadeOnDestroy: true


};

Postman: remotehost:xxxx/user?______________________

{
    "id": 1,
    "createdAt": "2017-12-30T12:51:10Z",
    "updatedAt": "2017-12-30T12:51:10Z",
    "name": "Drake Bell",
    "roles": "DEFAULT_USER",
    "email": "Drakebell09@hotmail.com",
    "password": "Youll never know :D",
    "lastlogout": "2017-12-30T12:51:10Z"
}

SQL Schema

describe testauthdb.user;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| createdAt | bigint(20)   | YES  |     | NULL    |                |
| updatedAt | bigint(20)   | YES  |     | NULL    |                |
| name      | varchar(255) | YES  |     | NULL    |                |
| roles     | varchar(255) | YES  |     | NULL    |                |
| email     | varchar(255) | YES  | UNI | NULL    |                |
| password  | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

node_modules/sails/lib/hooks/blueprints/actions/create.js

/**
 * Module dependencies
 */

var _ = require('@sailshq/lodash');
var async = require('async');
var formatUsageError = require('../formatUsageError');

/**
 * Create Record
 *
 * http://sailsjs.com/docs/reference/blueprint-api/create
 *
 * An API call to crete a single model instance using the specified attribute values.
 *
 */

module.exports = function createRecord (req, res) {

  var parseBlueprintOptions = req.options.parseBlueprintOptions || req._sails.config.blueprints.parseBlueprintOptions;

  // Set the blueprint action for parseBlueprintOptions.
  req.options.blueprintAction = 'create';

  var queryOptions = parseBlueprintOptions(req);
  var Model = req._sails.models[queryOptions.using];

  // Get the new record data.
  var data = queryOptions.newRecord;

  // Look for any many-to-one collections that are being set.
  // For example, User.create({pets: [1, 2, 3]}) where `pets` is a collection of `Pet`
  // via an `owner` attribute that is `model: 'user'`.
  // We need to know about these so that, if any of the new children already had parents,
  // those parents get `removedFrom` notifications.
  async.reduce(_.keys(Model.attributes), [], function(memo, attrName, nextAttrName) {

    var attrDef = Model.attributes[attrName];
    if (
      // Does this attribute represent a plural association.
      attrDef.collection &&
      // Is this attribute set with a non-empty array?
      _.isArray(data[attrName]) && data[attrName].length > 0 &&
      // Does this plural association have an inverse attribute on the related model?
      attrDef.via &&
      // Is that inverse attribute a singular association, making this a many-to-one relationship?
      req._sails.models[attrDef.collection].attributes[attrDef.via].model
    ) {
      // Create an `in` query looking for all child records whose primary keys match
      // those in the array that the new parent's association attribute (e.g. `pets`) is set to.
      var criteria = {};
      criteria[req._sails.models[attrDef.collection].primaryKey] = data[attrName];
      req._sails.models[attrDef.collection].find(criteria).exec(function(err, newChildren) {
        if (err) {return nextAttrName(err);}
        // For each child, see if the inverse attribute already has a value, and if so,
        // push a new `removedFrom` notification onto the list of those to send.
        _.each(newChildren, function(child) {
          if (child[attrDef.via]) {
            memo.push({
              id: child[attrDef.via],
              removedId: child[req._sails.models[attrDef.collection].primaryKey],
              attribute: attrName
            });
          }
        });
        return nextAttrName(undefined, memo);
      });
    }

    else {
      return nextAttrName(undefined, memo);
    }

  }, function (err, removedFromNotificationsToSend) {

    if (err) {return res.serverError(err);}


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // FUTURE: Use a database transaction here, if supported by the datastore.
    // e.g.
    // ```
    // Model.getDatastore().transaction(function during(db, proceed){ ... })
    // .exec(function afterwards(err, result){}));
    // ```
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    // Create new instance of model using data from params
    Model.create(data).meta(queryOptions.meta).exec(function created (err, newInstance) {

      // Differentiate between waterline-originated validation errors
      // and serious underlying issues. Respond with badRequest if a
      // validation error is encountered, w/ validation info, or if a
      // uniqueness constraint is violated.
      if (err) {
        switch (err.name) {
          case 'AdapterError':
            switch (err.code) {
              case 'E_UNIQUE': return res.badRequest(err);
              default: return res.serverError(err);
            }//•
          case 'UsageError': return res.badRequest(formatUsageError(err, req));
          default: return res.serverError(err);
        }
      }//-•

      // If we didn't fetch the new instance, just return 'OK'.
      if (!newInstance) {
        return res.ok();
      }

      // Look up and populate the new record (according to `populate` options in request / config)
      Model
      .findOne(newInstance[Model.primaryKey], queryOptions.populates)
      .exec(function foundAgain(err, populatedRecord) {
        if (err) { return res.serverError(err); }
        if (!populatedRecord) { return res.serverError('Could not find record after creating!'); }

        // If we have the pubsub hook, use the model class's publish method
        // to notify all subscribers about the created item
        if (req._sails.hooks.pubsub) {
          if (req.isSocket) {
            Model.subscribe(req, [populatedRecord[Model.primaryKey]]);
            Model._introduce(populatedRecord);
          }
          Model._publishCreate(populatedRecord, !req.options.mirror && req);
          if (removedFromNotificationsToSend.length) {
            _.each(removedFromNotificationsToSend, function(notification) {
              Model._publishRemove(notification.id, notification.attribute, notification.removedId, !req.options.mirror && req, {noReverse: true});
            });
          }
        }//>-

        // Send response
        res.ok(populatedRecord);
      }); // </foundAgain>

    });

  });



};

STACK TRACE

TypeError:Model.create(...) . meta不是/ home / username / / /的/home/username/api/node_modules/sails/lib/hooks/blueprints/actions/create.js:89:24中的函数api / node_modules / sails / node_modules / async / dist / async.js:421:16 at /home/username/api/node_modules/sails/node_modules/async/dist/async.js:2494:9 at / home / username /在iterateeCallback上补充(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:941:25)的api / node_modules / sails / node_modules / async / dist / async.js:421:16在/home/username/api/node_modules/sails/node_modules/async/dist/async.js:906:16 at /home/username/api/node_modules/sails/node_modules/async/dist/async.js:2491:13 athome/username/api/node_modules/sails/lib/hooks/blueprints/actions/create.js:71 :14在/home/username/api/node_modules/sails/node_modules/async/dist/async.js:2489:9补充(/home/username/api/node_modules/sails/node_modules/async/dist/async.js :946:17)a t iterateeCallback(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:931:17)位于/home/username/api/node_modules/sails/node_modules/async/dist/async.js: 906:16 at /home/username/api/node_modules/sails/node_modules/async/dist/async.js:2491:13 at / home / username / api / node_modules / sails / lib / hooks / blueprints / actions / create . js:71:14 athome/username/api/node_modules/sails/node_modules/async/dist/async.js:2489:9补充(/ home / username / api / node_modules / sails / node_modules / async / dist / async.js:946:17)在iterateeCallback(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:931:17)/ home / username / api / node_modules / sails / node_modules / async / dist / async.js:906:16 at /home/username/api/node_modules/sails/node_modules/async/dist/async.js:2491:13 at / home / username / api / node_modules / sails / lib / hooks / blueprints / actions / create.js:71:14 at /home/username/api/node_modules/sails/node_modules/async/dist/async.js:2489:9 at replenish(/ home / username / api / node_modules / SA ils / node_modules / async / dist / async.js:946:17)在/ home / username /的iterateeCallback(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:931:17) api / node_modules / sails / node_modules / async / dist / async.js:906:16 at / home /username/api/node_modules/sails/node_modules/async/dist/async.js:2491:13 at / home / username / api / node_modules / sails / lib / hooks / blueprints / actions / create.js:71:14 at /home/username/api/node_modules/sails/node_modules/async/dist/async.js:2489:9补充(/ home / username / api / node_modules / sails / node_modules / async / dist / async.js:946:17)在iterateeCallback(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:931: 17)/home/username/api/node_modules/sails/node_modules/async/dist/async.js:906:16 athome/username/api/node_modules/sails/node_modules/async/dist/async.js:2491 :13 at /home/username/api/node_modules/sails/lib/hooks/blueprints/actions/create.js:71:14 at/home/username/api/node_modules/sails/node_modules/async/dist/async.js:2489:9

1 回答

  • 0

    很抱歉给您带来不便,我的问题与routing.js有关 . 我没有达到正确的终点,因此很难确定错误 . 可能最终将此信息发布到sails forumn以清除错误日志记录 .

    This ticket can be closed (分数不够)

相关问题