Unique property fails in Sails.js
Asked Answered
S

6

12

The following code represents an Account Model in Sails.js v0.9.4 .

 module.exports = {

      attributes: {
        email: {
          type: 'email',
          unique: true,
          required: true
        },
        password:{
          type: 'string',
          minLength: 6,
          maxLength: 15,
          required:true
        }
      }

    };

When I send two POSTS and a PUT request via Postman to localhost:8080/account, the unique property of the email fails. Specifically, I send the following HTTP requests from Postman:

POST http://localhost:8080/[email protected]&password=123456  
POST http://localhost:8080/[email protected]&password=123456    
PUT  http://localhost:8080/account?id=1&[email protected]  
GET  http://localhost:8080/account

The last GET request shows me:

[
  {
    "email": "[email protected]",
    "password": "123456",
    "createdAt": "2013-09-30T18:33:00.415Z",
    "updatedAt": "2013-09-30T18:34:35.349Z",
    "id": 1
  },
  {
    "email": "[email protected]",
    "password": "123456",
    "createdAt": "2013-09-30T18:33:44.402Z",
    "updatedAt": "2013-09-30T18:33:44.402Z",
    "id": 2
  }
]

Should this happen?
*For those who don't know, Waterline generates by default an id which automatically increments in every insertion.

Suttee answered 30/9, 2013 at 18:47 Comment(2)
I could overcome this "faulty" behavior by setting autoPK:false.Suttee
When I put my autoPK to false, my id column got deleted.Leonardo
C
10

This is because your schema is not updated in your disk database (".tmp/disk.db").

You need to shutdown sails, drop your DB and restart sails. The DB will be reconstruct with your good schema.

Attention : the data will be drop too !

If you want keep your data, you can just update the schema part of ".tmp/disk.db".

What I have doing to keep data and rebuild schema by sails.js :

  1. copy ".tmp/disk.db"
  2. clean ".tmp/disk.db"
  3. shutdown sails.js
  4. start sails.js -> the database is empty and the schema is updated
  5. copy old "counters" part
  6. copy old "data" part

You must have this in your schema (file ".tmp/disk.db" -> "schema" part) for the unique field :

  "xxx": {
    "type": "string",
    "unique": true
  },

I hope this help you.

Codification answered 6/6, 2014 at 15:10 Comment(1)
A better solution is to tell Waterline to update the db schema. See the migrate setting, and make sure it is set to alter (models.migrate = 'alter')Mymya
E
6

I ran into this same issue. To solve it, you have to avoid using the 'disk' ORM adapter. For some reason it appears that it doesn't support uniqueness checks.

Other adapters such as mongo and mysql should support uniqueness checks, so this shouldn't be an issue outside of development.

For the course of development, change the default adapter in config/adapters.js from 'disk' to 'memory'. Should look like this:

module.exports.adapters = {

  // If you leave the adapter config unspecified 
  // in a model definition, 'default' will be used.
  'default': 'memory',

  // In-memory adapter for DEVELOPMENT ONLY
  memory: {
    module: 'sails-memory'
  },

  ...
};
Energize answered 1/10, 2013 at 11:54 Comment(6)
I forgot to mention that I tried the 'disk' and 'memory' adapters before posting my problem on stackoverflow. Didn't try a database though.Suttee
Did you try it in combination with autoPK: true?Energize
Yes I did.If you notice my POST requests don't require an id (that means it's enabled, i.e. autoPK:true).Suttee
What does config/adapters.js look like for you?Energize
The default (the one that comes when it is created with the sails command) config/adapters.js with 'default': 'memory'Suttee
Seems it's not fixed for localdisks on sails 0.10.x For sails-memory, it works good for me. Thanks.Shabuoth
M
1

I'm not certain this is the issue, but have you added schema:true to your models and adapters?

My mongo adapter config looks like this:

    module.exports.adapters = {
            'default': 'mongo',
            mongo: {
                    module: 'sails-mongo',
                    url: process.env.DB_URL,
                    schema: true
            }
    };

And my User model looks like this (trimmed a bit):

    module.exports = {
            schema: true,
            attributes: {
                    username: {
                            type: 'string',
                            required: true,
                            unique: true
                    }
                    //...
            }
    };
Moreville answered 2/10, 2013 at 21:32 Comment(1)
I don't think that the schema property matters when the default property is either disk or memory. My conclusion is based on the Sails model documentation. Out of curiosity I gave the default:memory and default:disk with schema:true a go. It didn't work. :( In the meantime I'll just switch to MongoDB and continue my work from there.Suttee
M
1

There is no need to delete current database to solve this, in stead change the waterline migrate option from safe to alter. This way the underlying database will adapt this setting.

I wouldn't recommend migrate: alter in a production environment, though. ;)


Here is my /config/local.js:

module.exports = {

    ... 

    models: {
        migrate: 'alter'
    },
}
Mymya answered 10/3, 2017 at 11:13 Comment(0)
G
1

According to the official documentation of sails

You should configure the option "migrate" in "alter" to create the schemas with their indexes

There's nothing wrong with adding or removing validations from your models as your app evolves. But once you go to production, there is one very important exception: unique. During development, when your app is configured to use migrate: 'alter', you can add or remove unique validations at will. However, if you are using migrate: safe (e.g. with your production database), you will want to update constraints/indices in your database, as well as migrate your data by hand.

http://sailsjs.com/documentation/concepts/models-and-orm/validations

Guilbert answered 23/8, 2017 at 21:49 Comment(0)
L
0
var InvoiceSchema = new Schema({
 email: {type: 'email', required: true}
  name : {type: String}
});
InvoiceScheme({email: 1}, {unique: true});

Set Uniquee In Nodejs

Loralyn answered 12/11, 2015 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.