Model attributes are basic pieces of information about a model. A model called Person might have attributes called firstName, lastName, phoneNumber, age, birthDate and emailAddress.
These options can be used to enforce various constraints and add special enhancements to our model attributes.
Specifies the type of data that will be stored in this attribute. One of:
When a record is created, if no value was supplied, the record will be created with the specified defaultsTo value. The supplied value can also be a function that waterline will run while creating the record.
attributes: {
  phoneNumber: {
    type: 'string',
    defaultsTo: '111-222-3333'
  },
  orderNumber: {
    type: 'text',
    defaultsTo: function() {
      return uuid.v4();
    }
  }
}
Sets up the attribute as an auto-increment key.  When a new record is added to the model, if a value for this attribute is not specified, it will be generated by incrementing the most recent record's value by one. Note: Attributes which specify autoIncrement should always be of type: 'integer'. Also, bear in mind that the level of support varies across different datastores. For instance, MySQL will not allow more than one auto-incrementing column per table.
attributes: {
  placeInLine: {
    type: 'integer',
    autoIncrement: true
  }
}
Ensures no two records will be allowed with the same value for the target attribute. This is an adapter-level constraint, so in most cases this will result in a unique index on the attribute being created in the underlying datastore.
attributes: {
  username: {
    type: 'string',
    unique: true
  }
}
When using MySQL with the
utf8mb4character set, you will need to add thesizeconstraint to the appropriate column in your table directly via MySQL. Otherwise, sincetype: 'string'is translated tovarchar(255)in the MySQL adapter, theunique: trueconstraint will cause an 'index too long' error:ER_INDEX_COLUMN_TOO_LONG: Index column size too large. The maximum column size is 767 bytes.
Use this attribute as the the primary key for the record. Only one attribute per model can be the primaryKey.  Note: This should never be used unless autoPK is set to false.
attributes: {
  uuid: {
    type: 'string',
    primaryKey: true,
    required: true
  }
}
A special validation property which only saves data which matches a whitelisted set of values.
attributes: {
  state: {
    type: 'string',
    enum: ['pending', 'approved', 'denied']
  }
}
If supported in the adapter, can be used to define the size of the attribute. For example in MySQL, size can be specified as a number (n) to create a column with the SQL data type: varchar(n).
attributes: {
  name: {
    type: 'string',
    size: 24
  }
}
Inside an attribute definition, you can specify a columnName to force Sails/Waterline to store data for that attribute in a specific column in the configured connection (i.e. database).  Be aware that this is not necessarily SQL-specific-- it will also work for MongoDB fields, etc.
While the columnName property is primarily designed for working with existing/legacy databases, it can also be useful in situations where your database is being shared by other applications, or you don't have access permissions to change the schema.
To store/fetch your model's numberOfWheels attribute into/from the number_of_round_rotating_things column:
// An attribute in one of your models:
  // ...
  numberOfWheels: {
    type: 'integer',
    columnName: 'number_of_round_rotating_things'
  }
  // ...
Now for a more thorough/realistic example.
Let's say you have a User model in your Sails app that looks like this:
// api/models/User.js
module.exports = {
  connection: 'shinyNewMySQLDatabase',
  attributes: {
    name: {
      type: 'string'
    },
    password: {
      type: 'string'
    },
    email: {
      type: 'email',
      unique: true
    }
  }
};
Everything works great, but instead of using an existing MySQL database sitting on a server somewhere that happens to house your app's intended users:
// config/connections.js
module.exports = {
  // ...
  // Existing users are in here!
  rustyOldMySQLDatabase: {
    adapter: 'sails-mysql',
    user: 'bofh',
    host: 'db.eleven.sameness.foo',
    password: 'Gh19R!?had9gzQ#Q#Q#%AdsghaDABAMR>##G<ADMBOVRH@)$(HTOADG!GNADSGADSGNBI@(',
    database: 'jonas'
  },
  // ...
};
Let's say there's a table called our_users in the old MySQL database that looks like this:
| the_primary_key | email_address | full_name | seriously_encrypted_password | 
|---|---|---|---|
| 7 | [email protected] | Mike McNeil | ranchdressing | 
| 14 | [email protected] | Nick Crumrine | thousandisland | 
In order to use this from Sails, you'd change your User model to look like this:
// api/models/User.js
module.exports = {
  connection: 'rustyOldMySQLDatabase',
  tableName: 'our_users',
  attributes: {
    id: {
      type: 'integer',
      unique: true,
      primaryKey: true,
      columnName: 'the_primary_key'
    },
    name: {
      type: 'string',
      columnName: 'full_name'
    },
    password: {
      type: 'string',
      columnName: 'seriously_encrypted_password'
    },
    email: {
      type: 'email',
      unique: true,
      columnName: 'email_address'
    }
  }
};
You might have noticed that we also used the
tableNameproperty in this example. This allows us to control the name of the table that will be used to house our data.The
columnNameproperty is not valid for plural associations (that is, attributes with theircollectionproperty set). If you’re trying to customize a join table for a many-to-many association, use thethroughproperty instead.The
columnNameproperty is not valid for plural associations (that is, attributes with theircollectionproperty set). If you’re trying to customize a join table for a many-to-many association, use thethroughproperty instead.