我正在尝试在Ubuntu 16.04数字海洋VPS上设置REST API。我遇到了这个错误' TypeError:Model.create(...)。meta不是函数'。在检查堆栈跟踪(下面发布)之后,该功能实际上就在那里。
需要注意几点:
1)我已经成功地做了一个帆升降机'命令确实创建了' 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)编译器没有捕获语法错误,因此您可能会在本文档中看到任何可能出现翻译问题的小错误。我认为唯一真正的错误是标题/堆栈跟踪中发布的错误。
任何指导都会非常感激,我花了很多时间试图解决这个问题。
版本
节点-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 /控制器/ 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 /模型/ 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();
});
});
}
};
配置/ 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
};
邮递员: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架构
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 /帆/ LIB /钩/蓝图/动作/ 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不是一个函数 at /home/username/api/node_modules/sails/lib/hooks/blueprints/actions/create.js:89:24 at /home/username/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/api/node_modules/sails/node_modules/async/dist/async.js:421:16 在补充(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:941:25) 在iterateeCallback(/home/username/api/node_modules/sails/node_modules/async/dist/async.js:931:17) at /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 在/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) at /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 在/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) at /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 在/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) at /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 在/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) at /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 在/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
答案 0 :(得分:0)
很抱歉给您带来不便,我的问题与routing.js有关。我没有达到正确的终点,因此很难确定错误。最终可能会将此信息发布到sails forumn以清除错误记录。
此票证可以关闭(不够点)