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
Related
I have the a mongoose model I'm trying to update right now using the .findOneAndUpdate method with the below code:
MyModel.findOneAndUpdate({ _id: "xxxxx", userId: "xxxxx" }, { $set: { completion:"xxxx", date: "xxxxx" } }, { new: true }, function(err, doc) {
if(err) {
return res.json({success: false, message: err.message});
}
res.json({success: true, message: 'success'});
});
When I log doc, it returns the updated model, but the model is not being saved to the database. Any thoughts on this would be greatly appreciated.
Model Code:
var MyModel = new Schema({
name: {
type: String,
required: true
},
date: {
type: Date,
required: true
},
userId: {
type: String,
required: true
},
completion: {
type: Boolean,
required: true
}
});
There are few issues as per your posted code:
1) MyModel is a Schema object, you will have to create a Model object like this -
var model = mongoose.Model('modelName', MyModel); // where MyModel is a Schema object
Then using the above model object you can run your findOneAndUpdate, like in your code (like model.findOneAndUpdate).
2) Secondly, in the MyModel Schema you have not given the collection name. You can put it in the options object which comes after the schema object argument. So you should put:
var MyModel = new Schema({schema object...}, {collection: 'mongodbCollectionName'});
If you do not give above option,mongoose would create a default collection using the model name.
I believe if (1) is not there, (2) is most likely causing the issue in your case.
In my model I have a many-to-many-through association between User, Program through ProgramStaff:
User.js:
module.exports = {
attributes: {
username: {
type: 'string',
required: true,
unique: true
},
programs: {
collection: 'Program',
via: 'program',
through: 'programstaff'
}
}
}
Program.js:
module.exports = {
attributes: {
name: {
type: 'string'
},
personnel:{
collection : 'User',
via: 'user',
through: 'programstaff'
}
}
}
ProgramStaff.js:
module.exports = {
attributes: {
program: {
model: 'Program'
},
user: {
model: 'User'
},
permissions: {
type: 'integer'
}
},
tableName: 'program_staff'
};
(I need to program-staff through table to hold some sort of permissions and a user-program based, otherwise, I'd just use a regular many-to-many association).
My question is - can I create a new User' and associate with (existing)Program` using the rest or shortcuts routes?
I've tried to send
user.programs = [programId]; // doesn't do anything (or error)
//or
user.programs = [{program: progamId}]; // creates new program even though I send valid id of existing program
//or
user.programs = [{program: { id: progamId}}]; // error
But neither seem to create the ProgramStaff record.
P.S. I know I can do it with a User.create and a nested ProgramStaff.create calls within a route, or a Create and then Update rest/shortcut calls but I was wondering about a "automatic" way to do that.
I must be misunderstanding this bullet point from the save documentation:
If you have any associations on the model they will currently be populated when you call .save(). This could cause issues with memory so to prevent this, you can take advantage of an experimental feature: passing in an options argument with populate: false set. Example: .save({ populate: false }, function() {})
http://sailsjs.com/documentation/reference/waterline-orm/records/save
My code...
//Person.js
attributes: {
name: {
type: 'string'
},
pets: {
collection: 'pet',
via: 'owner'
},
}
//Pet.js
attributes: {
animal: {
type: 'string'
},
owner: {
model: 'person'
}
}
//PersonController.js
create: function(req, res) {
Person.create({
name: 'Bob'
}).populate('pets').exec(function(err, person) {
person.pets.add({animal: 'dog'})
person.save(function(err) {
console.log(person);
});
})
}
And my output is Bob with no pets.
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
I am trying to create a custom attribute in my sails app and I am not getting any result back in my get call.
My code looks something like this:
module.exports = {
attributes: {
id: {
type: 'string',
primaryKey: true,
defaultsTo: function () {
return uuid.v4();
},
unique: true,
index: true,
uuidv4: true
},
name: {
type: 'string',
required: true
}
fullName: function(){
return this.name ;
}
};
I get back all the fields expect full Name
In my opinion the sailsjs model attributes only create corresponding column and get the column in database based on the type. In your case, the fullName has no type. so it does not know what to get from database.
However, if what you want is the returned json object has some extra fields, you can overwrite the toJSON function to add it.
module.exports={
attributes:
id: {
type: 'string',
primaryKey: true,
defaultsTo: function () {
return uuid.v4();
},
unique: true,
index: true,
uuidv4: true
},
name: {
type: 'string',
required: true
},
toJSON:function(){
var obj=this.toObject();
obj.fullName=obj.name;
return obj;
}
}
}
This issue is a little old, but I've a better answer:
module.exports = {
attributes: {
firstname : 'string',
lastname : 'string,
fullName: function () {
return this.firstname + ' ' + this.lastname
}
toJSON:function(){
var obj = this.toObject();
obj.fullName = this.fullName()
return obj;
}
}
}