Sails' Waterline email validation always failed - sails.js

I was working on my application and all was ok, but after reinstalling system to Windows 10 i always have an email validation fail. I don't really think this happens because of Windows 10, but it's only thing that was changed.
For testing i have created new shiny model:
module.exports = {
attributes: {
email: {
type: 'string',
required: true,
unique: true,
email: true
}
}
}
And if i start application with sails console and type TestModel.create({ email: 'alex#yahoo.com' }).exec(function(err, created) { console.log(err); console.log(created); }) i'll get something like this:
Error (E_VALIDATION) :: 1 attribute is invalid
at WLValidationError.WLError (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\error\WLError.js:26:15)
at new WLValidationError (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\error\WLValidationError.js:20:28)
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\query\validate.js:46:43
at allValidationsChecked (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:210:5)
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:49:16
at done (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:239:19)
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:40:16
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:201:14
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:49:16
at done (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:239:19)
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:40:16
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:164:64
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:162:20
at C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:230:13
at _arrayEach (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:81:9)
at _each (C:\Users\My name is Alex\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\node_modules\async\lib\async.js:72:13)
Invalid attributes sent to TestModel:
• email
• "email" validation rule failed for input: 'alex#yahoo.com'
If i disable email validation, all works nice.
{ email: 'alex#yahoo.com',
createdAt: '2015-08-08T21:09:25.118Z',
updatedAt: '2015-08-08T21:09:25.118Z',
id: 1 }
Own email validation method - isn't good solution.
I tried trivial stupid things like database reinstall, but it doesn't helps. Sorry for my bad english, hope i'll find answer here.

I have one weird solution now. I changed attribute type to 'email' and deleted email: true type.
module.exports = {
attributes: {
email: {
type: 'email',
required: true,
unique: true
}
}
};
And now it works. It's ok for me, but it is doesn't documented and i still want to know why default way doesn't works.

According to waterline docs:
Validations are defined directly in you Collection attributes. In addition you may set the attribute type to any supported Anchor type and Waterline will build a validation and set the schema type as a string for that attribute.
So when you set a type that is not one of the core types waterline will use it to validate the type in one of the validation rules supported by Anchor and keep the data as string
Therefore defining the schema like this will work:
module.exports = {
attributes: {
email: {
type: 'email',
required: true,
unique: true
}
}
};

Related

Model validation isUUID not working

I am currently trying to implement usage of UUID as s primary key for my user model in SailsJS application, using MongoDB. As for now the primary key is generated by other system, I would like to validate if uuid attribute is valid UUID.
Validation isEmail is working fine for me, but isUUID accepts string like "john-doe" so it looks like it is not working.
My configuration looks like this:
module.exports = {
primaryKey: 'uuid',
dontUseObjectIds: true,
attributes: {
uuid: {
type: 'string',
isUUID: true,
columnName: '_id',
required: true
},
...
}
}
My only thought is that the validaiton does not work against primary key attribute.
Any ideas what else might be wrong? Thanks

sailsjs one-way associations confusion

I am having a hard time wrapping my head around associations with sailsjs.
I have 2 models
Services
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
model: 'users',
via: 'id',
},
},
Users
attributes: {
email: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string'
}
},
So, a service is tied to a user (matching the id of the user).
I used to do a call like http://localhost:1337/Services?userId=userId
Now I would like to transition to associations using the above model attributes.
This works by calling the ID of the service just fine (it includes the users data as well), however if all i have is the user, how could I get the service
Doing the same call (http://localhost:1337/Services?userId=userId) returns and empty object.
Am I forced to actually have a one-to-one or one-to-many association? I don't understand why I can no longer use the userId field (stored in the DB) to do queries once I start using associations. I guess I am looking for the best of both worlds here.
EDIT:
Let me try make this more clear. Before trying to do associations, I could call this URL (using blueprint)
http://localhost:1337/Services?userId=userId
The Services model used to look like this
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
type: 'string',
required: true,
},
},
Then when a user is created, a service for that user is created with the userId matching the ID in the Users table.
Now I would like to implement associations using the above model scheme.
However, because (my best guess) the userId field of the service is mapped to the Users model, I am unable to search for a Server using the userId field that is stored.
I hope that makes sense? In another words, tryin to call
http://localhost:1337/Services?userId=userId
returns nothing when using associations but does return a value when I don't use associations

sequelize find parent table from child

I would like to find the parent table information of an object.
I have User hasMany Book
where Book has writer and assigned to user id.
Book has type, which is like fantasy, romance, history, scientific fiction... etc
So I want to find out the Book with type Scientific Fiction but not only for that, I also want the writer, which is User.
How can I find the book with its writer where where condition is given for books only? It seems like 'include' in Book.findAll( include: User) is not working; this tells me that include is only working for finding child tables not parent.
Here are some code for user
const User = sequelize.define('User', {
id: { type: DataTypes.STRING(6), field: 'ID', primaryKey : true }
}
associate: function(models) {
User.hasMany(models.Book, { foreignKey: 'userId' });
}
and book
const Book = sequelize.define('Book', {
id: { type: DataTypes.STRING(6), field: 'ID', primaryKey: true }, // primary key
userId: { type: DataTypes.STRING(6), field: 'USER_ID', primaryKey: true }
type: { type: DataTypes.STRING(20), field: 'TYPE'
}
Book has some more child table and I try to find those additional information in includes, so I guess I really need to find from Book.findAll(...)
Instead of User.findAll(include: Book).
Can anyone help?
I think I was making a mistake.
As soon as I changed
userId: { type: DataTypes.STRING(6), field: 'USER_ID', primaryKey: true }
to
userId: { type: DataTypes.STRING(6), field: 'USER_ID' }
include is working for belongsTo; and it finds the parent from child.
It seems like Sequelize has some problem with relation if there is more than one primary key declared in model...
If anyone does think this solves your problem, please share in reply so I can be more sure about it.
Thanks.

MongoDB - Duplicate Key Error After Changing Model To Allow Duplicates

I am using the mean stack. In Mongoose I defined a model with these properties:
var personSchema = new mongoose.Schema({
personName:{ type: String, unique: true, required: true, index:true },
start: { type: Date},
end: { type: Date }
});
However, when testing I realised I had made a mistake and that personName should not be unique. I removed the unique: true property and restarted MongoDB and the app.
However, I still get the duplicate key error when submitting.
Can anyone tell me what I'm doing wrong?
You might have created an index for the personName field.
Remove the index associated with field personName and try, it will work.
Reason:
when the field personName in the state "unique: true" index would be fine and now after removal of the state "unique: true". If we are trying to enter a record which is having a personName which is already there in the DB, then DB will throw Duplicate key error.

Create Both Parent/Child Associated Record in Sailsjs

I'm having a hard time trying to figure out if sails/waterline even does this.
(so an adequate answer would simply be if this is possible or not, I have been reading docs, looking through github issues and looking through code, but still not sure)
I have a one to one association setup where an 'account' has a 'contact'
I'm trying to create a contact within sails blueprints (so basically just using the create() method)
account =
{ name: 'Corp'
contact:{
firstName: 'Bob',
lastName: 'Jones'
}
}
so should Account.create(account).exec() create the account and the associated contact? Because I'm getting the following error
TypeError: Cannot convert null to object
My model is setup like so
account.js
module.exports = {
migrate: 'safe',
tableName: 'accounts',
autoPK: false,
attributes: {
id: {
type: 'INTEGER',
primaryKey: true,
autoIncrement: true
},
contactId: 'INTEGER',
name: {type: 'STRING', maxLength: 100},
contact: {
model: 'contact',
columnName:'contactId'
}
}
};
I'm using sails 10.0-rc8 / waterline 10.0-rc15
Creating an associated instance at the same time as its parent (aka "nested create") should work, but it's tricky to get things just right when you're dealing with a legacy database. In your case, the contactId attribute declaration is probably causing the issue, since Waterline expects the foreign key field to be implicit, not explicit. Try removing:
contactId: 'INTEGER',
entirely and see where that gets you.
After some research I found out that as of version 0.10.0-rc15 of waterline you can NOT have a customized foreign keys. In the above model if I change the "contactId" column to just "contact" (basically make it look exactly like it does in the docs. Then it works.
I made the following bug report
https://github.com/balderdashy/waterline/issues/529