var mysql = require("mysql");
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'nodejs'
});
exports.players_list = function(req, res) {
var data = {title: "", res: {}};
if (authenticate(req, res)) {
results_aaa(function(result) {
console.log(result);
res.render('players/players', {title: 'Players List', res: result});
});
} else {
req.session.error = 'Please login to continue.';
res.redirect('/login');
}
};
function results_aaa(callback) {
teams(function(res) {
callback(res)
});
}
function teams(callback) {
var query = connection.query("select * from team", function(err, result, fields) {
for (var index in result)
{
players(result[index].id, function(results) {
callback(results);
});
}
});
}
function players(id, callback) {
query("SELECT * FROM players where team = " + id, function(results) {
callback(results);
});
}
function query(sql, callback) {
connection.query(sql, function(error, results, fields) {
callback(results);
});
}
I am trying to group the data of a particular team with team players.
And i'm getting partial output. But if i use console.log(), i am able to see the entire output in console
Output in console looks like this.
Express server listening on port 8081
[ { id: 2, player_name: 'Virat Kohli', team: '1' },
{ id: 4, player_name: 'A B DeVilliers', team: '1' },
{ id: 6, player_name: 'Chris Gayle', team: '1' } ]
GET /players 200 162ms - 638
[ { id: 7, player_name: 'Ajinkya Rahane', team: '2' },
{ id: 8, player_name: 'Shane Watson', team: '2' },
{ id: 9, player_name: 'Stuart Binny', team: '2' },
{ id: 10, player_name: 'Karun Nair', team: '2' },
{ id: 11, player_name: 'Sanju Samson', team: '2' } ]
[ { id: 1, player_name: 'Virender Sehwag', team: '3' },
{ id: 3, player_name: 'David Miller', team: '3' },
{ id: 5, player_name: 'Shaun Marsh', team: '3' } ]
Only team id with 1 is appearing in jade view.
And is the procedure followed is correct. I am new to node js.
Thanks in advance:)
This is because you are sending the response after you receive the first callback, i.e., the team1 results and before you receive the other two, the 2nd and 3rd team results.
In function teams(), use
if(index == result.length-1) { callback(results); }
instead of just
callback(results);
inside the for loop.
Related
I'm trying to do unit testing on my nodejs-express method with sequelize-mock.
Controller
const getDetailsByUserId = async (id) => {
try {
const userId = id ?? 0;
const details = await Model.findAll(
{
raw: true,
where: { user_id: userId }
}
);
if (details && details .length > 0) {
return {
status: 200,
success: true,
message: 'details found.',
data: details
}
}
return {
status: 404,
success: false,
message: 'details not found',
data: []
}
} catch (error) {
return {
status: 500,
success: false,
message: error.message || "An error occurred while getting details.",
data: null
}
}
}
Test
jest.mock('../models/details', () => () => {
const SequelizeMock = require("sequelize-mock");
const dbMock = new SequelizeMock();
return dbMock.define('users', [
{
id: 1,
user_id: 123
name: 'John Doe 1'
},
{
id: 2,
user_id: 456
name: 'John Doe 2'
},
{
id: 3,
user_id: 789
name: 'John Doe 3'
}
]);
});
test('should return 404 and an empty array', async () => {
const userId = 147;
const details = await controller.getDetailsByUserId(userId);
expect(details.status).toEqual(404);
});
I always get the status of 200 instead of 404 here. I checked the returned data and it's returning the records of the defined mocked model.
Actual Result:
[
fakeModelInstance {
options: {
timestamps: true,
paranoid: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined,
isNewRecord: true
},
_values: {
'0': [Object],
'1': [Object],
'2': [Object],
user_id: 147,
id: 1,
createdAt: 2021-09-18T00:55:25.976Z,
updatedAt: 2021-09-18T00:55:25.976Z
},
dataValues: {
'0': [Object],
'1': [Object],
'2': [Object],
user_id: 147,
id: 1,
createdAt: 2021-09-18T00:55:25.976Z,
updatedAt: 2021-09-18T00:55:25.976Z
},
hasPrimaryKeys: true,
__validationErrors: []
}
]
QUESTIONS:
Is there something I can do to get the expected result (empty array) for this scenario?
the raw: true seems to be not working when it is mocked. Is there a way could log the result on raw object?
NOTE: This only happens on the unit testing. When accessing the endpoint on postman it returns the expected result.
According to the docs, findAll() will always return an array of a single result based on the where query in the options. This is why you will never get an empty array.
See more: https://sequelize-mock.readthedocs.io/en/stable/api/model/#findalloptions-promisearrayinstance
I want to update the wallet table when I deposit an amount in the wallet.
My code is like this:
model wallet.js
'use strict';
module.exports = (sequelize, DataTypes) => {
var Model = sequelize.define('wallet', {
id: {
type: DataTypes.INTEGER,
field: 'id',
primaryKey: true,
autoIncrement: true
},
cid: {
type: DataTypes.STRING,
field: 'cid'
},
deposit: {
type: DataTypes.INTEGER,
field: 'deposit'
},
withdrawal: {
type: DataTypes.INTEGER,
field: 'withdrawal'
},
available: {
type: DataTypes.INTEGER,
field: 'available',
},
comments: {
type: DataTypes.DATE,
field: 'comments'
},
online: {
type: DataTypes.STRING,
field: 'online'
}
}, {
tableName: 'wallet',
timestamps: false
});
Model.associate = function (models) {
this.orders = this.hasOne(models.orders, {
as: 'orders',
foreignKey: 'wid'
});
};
Model.prototype.toWeb = function (pw) {
let json = this.toJSON();
return json;
};
return Model;
};
here the wallet deposit is happening here i am using set method to update the wallet
walletcontroller.js
const deposit = async function (req, res) {
res.setHeader('Content-Type', 'application/json');
let err, wallet, existingWallet;
let wallet_info = req.body;
[err, existingWallet] = await to(Wallet.findAll({
limit: 1,
where: {
cid: wallet_info.cid,
},
order: [
['id', 'DESC']
]
}));
[err, wallet] = await to(Wallet.set(wallet_info, {
limit: 1,
where: {
cid: wallet_info.cid,
},
order: [
['id', 'DESC']
]
}));
if (err) return ReE(res, err, 422);
if (existingWallet[0] != 'undefined') {
wallet.available = existingWallet[0].available + wallet_info.deposit;
wallet.comments = new Date();
} else {
wallet.available = wallet_info.deposit;
wallet.comments = new Date();
}
console.log("avalible balance:" + wallet.available);
[err, wallet] = await to(wallet.save());
if (err) return ReE(res, err, 422);
return ReS(res, {
wallet: wallet.toWeb()
}, 201);
}
module.exports.deposit = deposit;
please help me out how to update the wallet... when i am callig api here my err msg looks like this
Executing (default): SELECT `id`, `cid`, `deposit`, `withdrawal`, `available`, `comments`, `online` FROM `wallet` AS `wallet` WHERE `wallet`.`cid` = '33' ORDER BY `wallet`.`id` DESC LIMIT 1;
Error:
Uncaught Error { filename: '\\cl-api-master\\controllers\\WalletController.js',
line: 67,
row: 37,
message: 'Wallet.set is not a function',
type: 'TypeError',
stack: 'TypeError: Wallet.set is not a function\n at deposit (E:\\cl-api-master\\controllers\\WalletController.js:67:37)\n at <anonymous>',
arguments: undefined }
POST /v1/wallet/deposit - - ms - -
For Edition, you can simply use -
data.update = await Wallet.update(
{
available: available,
comments: new Date()
},
{
where: { cid: wallet_info.cid }
}
);
available variable can be set using if else condition afterward running above update query.
My current models:
let Book = sequelize.define('book', {
title: Sequelize.STRING,
author: Sequelize.STRING,
...
});
let Recommendation = sequelize.define('recommendations', {
reasoning: Sequelize.STRING,
rating: Sequelize.FLOAT,
});
Book.belongsToMany(Recommendation, {through: 'bookrecommendation'});
Recommendation.belongsToMany(Book, {through: 'bookrecommendation'});
When executing code below method addRecommendation to add Recommendation for Book I get an error Error: Invalid value [object Promise]
Book.findOrCreate({
where: { id: '1' }, defaults: {
author: 'test',
title: 'test'
}
})
.spread(function (b, createdBook) {
const rec = Recommendation.create(
{
reasoning: 'test',
rating: 1
});
b.addRecommendation(rec).then((result) => {
}, (error) => {
console.log(error);
})
}
The issue here is that rec is a promise.
This should solve the issue
Book.findOrCreate({ where: { id: '1' }, defaults: {
author: 'test',
title: 'test'
}}).spread(function (b, createdBook) {
Recommendation.create({
reasoning: 'test',
rating: 1
}).then((rec) => {
b.addRecommendation(rec).then((result) => {}, (error) => {
console.log(error);
})
})
So, I'm creating a small application using SailsJS. My database is MySQL.
When I'm testing, first I create a "market" record, then a "stock" record linked to "market" and in another moment, I retrieve this stock record.
I have the following models:
Stock model:
module.exports = {
attributes: {
intern_id: {
type: 'string'
},
tick: {
type: 'string'
},
market: {
model: 'market'
}
}
};
Market model:
module.exports = {
attributes: {
tick: {
type: 'string'
},
name: {
type: 'string'
},
description: {
type: 'string'
},
stocks: {
collection: 'stock',
via: 'market'
},
}
}
Then, first I create a "market" and use the object returned to associate with my "stock" object:
Create and get my market record:
Market.create({tick: 'BVMF', name: 'Bovespa', description: 'Bolsa de Valores'}).exec(function(err, market) {
if(err) done(err);
});
var market = Market.findOne({tick: 'BVMF'}).then(function(results){return results;});
Create my stock record:
Stock.create({intern_id: '1234', tick: 'VALE5', description: 'Vale SA', market: market}).exec(function(err, stock) {
if(err) done(err);
});
And then, when I try to get back this stock, the market object is not retrieved, even if I call populate('market'):
Stock.findOne({tick: 'VALE5'}).populate('market').exec(function(err, record) {
console.log(record);
});
Not too much information, but I guess.
Instead:
Stock.findOne({tick: 'VALE5'}).populate('market').exec(function(err, record) {
console.log(marketObj);
});
Should be:
Stock.findOne({tick: 'VALE5'}).populate('market').exec(function(err, record) {
console.log(record);
});
Second answer:
You forgot about asynchronous. You should do this like that:
Market.create({tick: 'BVMF', name: 'Bovespa', description: 'Bolsa de Valores'}).exec(function(err, market) {
if(err){
done(err);
} else {
Stock.create({intern_id: '1234', tick: 'VALE5', description: 'Vale SA', market: market.id}).exec(function(err, stock) {
if(err){
done(err);
} else {
Stock.findOne({tick: stock.tick}).populate('market').exec(function(err, record) {
console.log(record); // and there is your "Stock" with populated "market"
});
}
});
}
});
Im using 'json-csv' library to create a csv from a users arrays with nested objects and arrays.
var users = [
{
subscriptions: [
{
package : {
name: 'Grammar'
},
state: 'EXPIRED',
timerange: {
period : 5550
},
transaction:{
amount: 10000
}
},
{
package : {
name: 'GK'
},
state: 'ACTIVE',
timerange: {
period : 30
},
transaction:{
amount: 10340
}
},
],
account:{
balance: 200
},
name: "Johhy Moe",
email: null,
user_id: "123456789",
username: null,
user_type: "facebook",
id: 3,
createdAt: "2016-07-11T08:02:40.000Z",
updatedAt: "2016-07-11T08:02:40.000Z",
},
{
subscriptions: [
{
package : {
name: 'GK'
},
state: 'EXPIRED',
timerange: {
period : 42
},
transaction:{
amount: 5252
}
},
{
package : {
name: 'MATH'
},
state: 'ACTIVE',
timerange: {
period : 25
},
transaction:{
amount: 200
}
}
],
account:{
balance: 1500
},
name: "John Doe",
email: null,
user_id: "123456789",
username: null,
user_type: "facebook",
id: 7,
createdAt: "2016-07-29T06:44:18.000Z",
updatedAt: "2016-07-29T06:44:18.000Z"
},
]
Now i want the generated csv to be like this
USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD
3,Johhy Moe,123456789,200,Grammar,10000,EXPIRED,5550
3,Johhy Moe,123456789,200,GK,10340,ACTIVE,30
7,John Doe,123456789,1500,GK,5252,EXPIRED,30
7,John Doe,123456789,1500,MATH,200,ACTIVE,25
As you see if there are two objects inside subscription array for each user, i want to repeat that user again but with different subscription data.
I've thought of using the library because my users array can go up to thousands of users with hundreds of subscription.
And i'm at a loss to what i should do.
my Code:
var options= {
fields : [
{
name : 'id',
label : 'USERID'
},
{
name : 'name',
label : 'Name'
},
{
name : 'user_id',
label : 'FBID'
},
{
name : 'account.balance',
label : 'ACCOUNT'
},
{
name: '',
label: 'Subscription'
}
]
}
var source = es.readArray(users)
source
.pipe(jsoncsv.csv(options))
.pipe(res)
I dont want to use a library also. So if someone could provide me with a resource to make my own csv file with strings and also using streams , that would be great. Thanks!!
This will solve your problem. Now you just have to change console.log to fs and write to your file.
var json2csv = function (json, listKeys) {
var str = "";
var prefix = "";
for (var i = 0; i < listKeys.length; i++) {
str += prefix + json[listKeys[i]];
prefix = ",";
}
return str;
};
var async = require('async');
var csvData = ['USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD'];
async.each(users, function (user, callback) {
var csvRow1 = {
USERID: user.id,
NAME: user.name,
FBID: user.user_id,
ACCOUNT: user.account.balance
};
async.each(user.subscriptions, function (subscription, callback) {
var csvRow2 = JSON.parse(JSON.stringify(csvRow1));
csvRow2.SUBSCRIPTION = subscription.package.name;
csvRow2.PRICE = subscription.transaction.amount;
csvRow2.STATE = subscription.state;
csvRow2.TIMEPERIOD = subscription.timerange.period;
csvData.push(json2csv(csvRow2, ['USERID', 'NAME', 'FBID', 'ACCOUNT', 'SUBSCRIPTION', 'PRICE', 'STATE', 'TIMEPERIOD']));
callback(null);
}, function (err) {
callback(err);
});
}, function (err) {
if (err) {
// return err;
} else {
// return csvData;
}
});