I'm trying to create 2 user in parallel and wait for it to be created after do something else. I was trying to use:
Promise.all([User.create(usr1), User.create(usr2), User.create(usr3)]).then(function(){
console.log("\o/");
}
without luck, because User.create() do not return a Promise.
I also tried:
User.create([usr1, usr2]).then(function(){
console.log('x')
})
Error that I get:
[Error (E_VALIDATION) 1 attribute is invalid] Invalid attributes sent to undefined:
• user
• A record with that user already exists (null).
Ugly code that is working:
User.create([usr1]).then(function(){
User.create[usr2].then(function(){ console.log('x') });
});
Also work with .exec()
User.create([usr1, usr2]).exec(function(){
console.log('x')
})
How can I use Promise or just waterline to create two user?
EDIT:
1) Calling it in mocha test
Code here
attributes: {
name: {
type: 'string',
required: true
},
email: {
type: 'email',
required: true,
unique: true
},
password: {
type: 'string',
minLength: 6,
},
//Association One-to-One, but using 'collection' to mantain sync updating
employer: {
collection: 'employer',
via: 'user'
},
employee: {
collection: 'employee',
via: 'user'
},
//Google Signin ID
googleId: 'string',
//Access token from the Google Authorization Server
googleAccessToken: 'string',
resetPasswordToken: String,
resetPasswordExpires: Date,
toJSON: function() {
var obj = this.toObject();
delete obj.password;
delete obj.resetPasswordToken;
delete obj.resetPasswordExpires;
return obj;
}
},
EDIT2:
This error only happens when I use sails-disk, in sails-mongo work
Related
I have an association between Client and Budget as follows:
//Client.js
module.exports = {
primaryKey: 'id',
attributes: {
id: {
type: 'number',
unique: true,
autoIncrement: true
},
name: {
type: 'string'
},
phone: {
type: 'string',
unique: true
},
email: {
type: 'string',
unique: true
},
budgets: {
collection: 'budget',
via: 'client'
},
}
};
// Budget.js
module.exports = {
primaryKey: 'id',
attributes: {
id: {
type: 'number',
unique: true,
autoIncrement: true
},
client: {
model: 'client'
},
budgetItems: {
type: 'json'
}
}
};
So, POST is working for both entities so I can create both of them, but:
GET /budget/1
returns the budget and the id of the associated client.
GET /budget/1/client
returns the client id without populating(as i've seen in documentation it should be populated).
GET /client/1
returns the client attributes and there is not a field related with budgets.
GET /client/1/budgets
returns 404 NOT FOUND
I'm following this and this official documentation
So what I could be missing?
Is just generating one direction associations, and I've compared with official documentation and third party examples and my code looks fine.
Thanks in advance!
Update:
I still looking for troubles and if I run sails with --silly option it shows there is the following route available:
Binding route :: get /client/:parentid/budgets POLICY: localize
Binding route :: get /client/:parentid/budgets POLICY: isauth
Binding route :: get /client/:parentid/budgets BLUEPRINT: populate
but if I try to access returns a 404 Not Found and console shows the following error, thrown by populate.js from Sails core code:
verbo: In populate blueprint action: Specified parent record (1)
does not have a budgets.
Update2:
Debugging with sails console I've seen the association is generated properly. Given Client.findOne({id: 1}).populate('budgets').then((client)=>{console.log(client)}) print the client attributes and the associated Budgets but still return 404 Not Found when: GET /client/1/budgets
I have created quick demo and it seems working fine for me.
For demo I have used sails version 1.2.2 and sails-disk as database and there is some minor difference in Model attributes as below
Client.js
module.exports = {
attributes: {
name: {
type: 'string'
},
phone: {
type: 'string',
unique: true,
required: true
},
email: {
type: 'string',
unique: true,
required: true
},
budgets: {
collection: 'Budget', // <<== B is capital here
via: 'client'
},
},
};
Budget.js
module.exports = {
attributes: {
client: {
model: 'Client' // <<== C is capital here
},
budgetItems: {
type: 'json'
}
},
};
Let me know if this is helpful
thanks to SailsJS team we've found the problem and it was related with a third party package and just had to remove it from my project.
It was sails-hook-deep-orm who's owner has been warned. I hope someone with the same issue will reach this post.
Thanks u all anyway!!
The issue is available there
I have 2 models in my postgresql db and using sequelize and node:
Users
Transactions
and are associated like this:
UserModel.hasMany(TransactionModel, { as: 'sentTransactions', foreignKey: 'senderId' });
UserModel.hasMany(TransactionModel, { as: 'receivedTransactions', foreignKey: 'receiverId' });
UserModel.belongsToMany(TransactionModel, { as: 'transactionLikes', through: 'UserLike', foreignKey: 'userId' });
TransactionModel.belongsTo(UserModel, { as: 'receiver' });
TransactionModel.belongsTo(UserModel, { as: 'sender' });
TransactionModel.belongsToMany(UserModel, { as: 'likers', through: 'UserLike', foreignKey: 'transactionId' });
Which means a user has many received and sent transactions and each user can "like" many transactions.
How can I delete a transaction and remove all associations (receiver, sender, liker)? I don't want to delete the users too.
I would also like to update the User Model which is defined like this, in order to add an "email" property:
const UserModel = db.define('user', {
id: { type: Sequelize.STRING, unique: true, primaryKey: true },
firstName: { type: Sequelize.STRING },
lastName: { type: Sequelize.STRING },
username: {
type: Sequelize.STRING,
unique: {
args: true,
msg: USERNAME_IS_TAKEN,
},
}
How can I update the model? What will happen to the existing instances?
Thank you in advance for your help!
According to this tutorial your M:N relation should work as you expect it out of the box:
For n:m, the default for both is CASCADE. This means, that if you delete or update a row from one side of an n:m association, all the rows in the join table referencing that row will also be deleted or updated.
Further more, to enforce the CASCADE behavior you may also pass onDelete option to the association calls. Something like this should do the trick:
TransactionModel.belongsToMany(UserModel, { as: 'likers', through: 'UserLike', foreignKey: 'transactionId', onDelete: 'CASCADE' });
Adding an email property to the User Model should be as easy as that:
const UserModel = db.define('user', {
id: {
type: Sequelize.STRING,
unique: true,
primaryKey: true
},
firstName: { type: Sequelize.STRING },
lastName: { type: Sequelize.STRING },
username: {
type: Sequelize.STRING,
unique: {
args: true,
msg: USERNAME_IS_TAKEN,
}
},
email: { type: Sequelize.STRING }
});
I am using Sails.js version 1.0.2. I am trying to assign uuid as primary key throughout the application. I tried putting
id: { type: 'string', defaultsTo:uuid.v4() } in model.js but it's saying Primary keys must be unique therefore can't contain a default value.
_________________EDIT_______________
I tried this code in my domain
beforeCreate: function (modelObj, next) {
modelObj.id = uuidv4.v4();
next();
}
And edit my Model.js configuration is like :
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string',required:true},
}
beforeCreate method never executes and throw the error while creating the record like:
error: Sending 500 ("Server Error") response:
{ UsageError: Invalid new record.
Details:
Missing value for required attribute `id`. Expected a string, but
instead, got: undefined
Please let me know if I am doing anything wrong.
Thanks
You can do something like this instead of giving default value
beforeCreate: function (modelObj, next) {
modelObj.id = uuid.v4();
next();
}
You can add this piece of function in your model. This gets invoked whenever there is a create operation on model.
Your Model.js should looks something like this
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string',required:true},
},
beforeCreate: function (modelObj, next) {
modelObj.id = uuid.v4();
next();
}
Sample code of my Controller and Model,
TestController.js
module.exports = {
create: function(req, res) {
Test.create({"name": "arshad"})
.then(function(result){
res.send("done");
})
}
};
Test.js Model
module.exports = {
attributes: {
id: { type: 'string', required: true },
name: { type: 'string' }
},
beforeCreate: function(obj, next) {
obj.id = 'someId';
next();
}
};
This is how your model and controller will look like. This will add someId as defined in beforeCreate function to the object
In your case you are using uuid package. Check in debugging mode whether uuid reference is available in beforeCreate or not
I'm giving a try to the beta version of SailsJS (v1.0.0-32) and I'm having some issues while configuring a custom id. Bellow you'll find my current configuration:
The modelExample.js
module.exports = {
attributes: {
id:{
type: 'string',
columnName: '_id'
},
attr: {
type: 'number'
}
}
}
The model config config/models.js
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string', columnName: '_id' },
}
The element trying to be inserted:
{id:"600000", attr:40}
The error I get when trying to create a record with an attribute "id" included in the element trying to be created:
AdapterError: Unexpected error from database adapter: Invalid primary key value provided for `id`. Cannot interpret `600000` as a Mongo id.
(Usually, this is the result of a bug in application logic.)
Seems that mongo does not like the string 600000 as an id, but I'm not sure if maybe I'm misunderstanding something related to ids in mongo. In the old version of sails, I never had this issue since the id override was straightforward.
For more information, the sails-mongo adapter version is: "sails-mongo": "^1.0.0-5"
In order to use non-ObjectID primary keys with sails-mongo in Sails 1.0, you have to set dontUseObjectIds: true in your model, for example:
// api/models/User.js
module.exports = {
dontUseObjectIds: true,
attributes: {
id: { type: 'number', columnName: '_id' }, // <-- still need to set `columnName`!
name: { type: 'string' },
...etc...
}
}
This is implemented as of sails-mongo v1.0.0-7.
I have these models:
// Material.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
source_info: {
type: 'string',
required: true
},
category: { model: 'category_mat' }
}
};
and:
// Category_Mat.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
material:{
collection: 'material',
via: 'category'
}
},
};
but when I run the app I get this error:
/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:82
throw new Error('Trying to access a collection ' + collection + ' that is
^
Error: Trying to access a collection category_mat that is not defined.
at ForeignKeys.findPrimaryKey (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:82:11)
at ForeignKeys.replaceKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:53:27)
at new ForeignKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:30:10)
at new module.exports (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema.js:30:17)
at Waterline.initialize (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline.js:106:17)
at buildORM (/usr/local/lib/node_modules/sails/lib/hooks/orm/build-orm.js:48:15)
at Array.async.auto.instantiatedCollections [as 1] (/usr/local/lib/node_modules/sails/lib/hooks/orm/index.js:191:11)
at listener (/usr/local/lib/node_modules/sails/node_modules/async/lib/async.js:465:46)
at /usr/local/lib/node_modules/sails/node_modules/async/lib/async.js:419:17
at Array.forEach (native)
I used this documentation as reference:
http://sailsjs.org/#/documentation/concepts/ORM/Associations/OnetoMany.html
so I don't know what I'm missing or if there is a configuration that I have to do... any help?
Maybe it is because "category-mat" used on Material.js is not defined anywhere... try
// Category_Mat.js
module.exports = {
identity: 'category_mat',
attributes: {
name: {
type: 'string',
required: true
},
material:{
collection: 'material',
via: 'category'
}
},
};
If this works the only side effect is that even if you have config/globals.js/models set to "true", you won't be able to access the model in the controllers by using "Category_Mat". You will either have to use "sails.models.category_mat" or just "category_mat".