Getters & setters

It is possible to define 'object-property' getters and setter functions on your models, these can be used both for 'protecting' properties that map to database fields and for defining 'pseudo' properties.

Getters and Setters can be defined in 2 ways (you can mix and match these 2 approaches):

  • as part of a single property definition
  • as part of a model options

N.B: If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence.

Defining as part of a property

  1. class Employee extends Model {}
  2. Employee.init({
  3. name: {
  4. type: Sequelize.STRING,
  5. allowNull: false,
  6. get() {
  7. const title = this.getDataValue('title');
  8. // 'this' allows you to access attributes of the instance
  9. return this.getDataValue('name') + ' (' + title + ')';
  10. },
  11. },
  12. title: {
  13. type: Sequelize.STRING,
  14. allowNull: false,
  15. set(val) {
  16. this.setDataValue('title', val.toUpperCase());
  17. }
  18. }
  19. }, { sequelize, modelName: 'employee' });
  20. Employee
  21. .create({ name: 'John Doe', title: 'senior engineer' })
  22. .then(employee => {
  23. console.log(employee.get('name')); // John Doe (SENIOR ENGINEER)
  24. console.log(employee.get('title')); // SENIOR ENGINEER
  25. })

Defining as part of the model options

Below is an example of defining the getters and setters in the model options.

The fullName getter, is an example of how you can define pseudo properties on your models - attributes which are not actually part of your database schema. In fact, pseudo properties can be defined in two ways: using model getters, or by using a column with the VIRTUAL datatype. Virtual datatypes can have validations, while getters for virtual attributes cannot.

Note that the this.firstname and this.lastname references in the fullName getter function will trigger a call to the respective getter functions. If you do not want that then use the getDataValue() method to access the raw value (see below).

  1. class Foo extends Model {
  2. get fullName() {
  3. return this.firstname + ' ' + this.lastname;
  4. }
  5. set fullName(value) {
  6. const names = value.split(' ');
  7. this.setDataValue('firstname', names.slice(0, -1).join(' '));
  8. this.setDataValue('lastname', names.slice(-1).join(' '));
  9. }
  10. }
  11. Foo.init({
  12. firstname: Sequelize.STRING,
  13. lastname: Sequelize.STRING
  14. }, {
  15. sequelize,
  16. modelName: 'foo'
  17. });
  18. // Or with `sequelize.define`
  19. sequelize.define('Foo', {
  20. firstname: Sequelize.STRING,
  21. lastname: Sequelize.STRING
  22. }, {
  23. getterMethods: {
  24. fullName() {
  25. return this.firstname + ' ' + this.lastname;
  26. }
  27. },
  28. setterMethods: {
  29. fullName(value) {
  30. const names = value.split(' ');
  31. this.setDataValue('firstname', names.slice(0, -1).join(' '));
  32. this.setDataValue('lastname', names.slice(-1).join(' '));
  33. }
  34. }
  35. });

Helper functions for use inside getter and setter definitions

  • retrieving an underlying property value - always use this.getDataValue()
  1. /* a getter for 'title' property */
  2. get() {
  3. return this.getDataValue('title')
  4. }
  • setting an underlying property value - always use this.setDataValue()
  1. /* a setter for 'title' property */
  2. set(title) {
  3. this.setDataValue('title', title.toString().toLowerCase());
  4. }

N.B: It is important to stick to using the setDataValue() and getDataValue() functions (as opposed to accessing the underlying "data values" property directly) - doing so protects your custom getters and setters from changes in the underlying model implementations.