Sling Academy
Home/Node.js/Sequelize.js: Using afterValidate and validationFailed hooks

Sequelize.js: Using afterValidate and validationFailed hooks

Last updated: December 29, 2023

Introduction

One of the core features of Sequelize.js, a promise-based Node.js ORM (Object-Relational Mapping) library, is model validation. Validation in Sequelize allows developers to ensure that the data being saved to the database meets specific criteria and rules. Moreover, hooks are functions that are called before or after certain lifecycle events of the models, such as validation, creation, updates, etc. The afterValidate and validationFailed hooks play a significant role in extending the traditional validation capabilities by allowing additional actions to be performed either after the validation succeeds or if validation fails, respectively.

In this tutorial, we’ll explore how to effectively use the afterValidate and validationFailed hooks in Sequelize.js, provide examples of their implementation, and offer advanced techniques for utilizing them in your applications.

Basic Usage of afterValidate Hook

The afterValidate hook is executed after model validation has completed successfully. It’s the perfect place to add custom operations or checks that rely on a successfully completed validation. Here’s a fundamental use case:

const { Model, DataTypes } =require('sequelize');
 const sequelize = new Sequelize('sqlite::memory:');

class User extends Model {}
User.init({
  username: {
    type: DataTypes.STRING,
    validate: {
      notEmpty: true
    }
  },
  email: {
    type: DataTypes.STRING,
    validate: {
      isEmail: true
    }
  }},
  { sequelize, modelName: 'user' },
);

User.afterValidate('customAfterValidate', (user, options) => {
 console.log('The afterValidate hook has been triggered.');
});

Understanding the validationFailed Hook

Conversely, the validationFailed hook gets called when validation fails. It allows you to execute custom error handling logic or recover from the failure. The following is a simple example:

User.addHook('validationFailed', 'customValidationFailed', (instance, options, error) => {
 console.log('Validation failed for instance:', instance);
 console.log('Encountered error:', error);
});

Advanced Scenario: Custom Validation Logic

Let’s advance our understanding by incorporating custom validation logic into our hooks:

class User extends Model {}
User.init({...});

User.afterValidate('checkForAdmin', (user, options) => {
 if (user.username === 'admin' && !user.isAdmin) {
    throw new Error('Only Admins Can Have The Username as "admin".');
  }
});

User.addHook('validationFailed', (instance, options, error) => {
 if (error.errors[0].path === 'isAdmin' && instance.username === 'admin') {
    instance.isAdmin = true; // Recover by setting correct flag
  }
});

With afterValidate, we add a rule that throws an error if ‘admin’ username had been chosen without the proper admin flag. And, if a validation fails due to the ‘isAdmin’ field, validationFailed corrects the flag for username ‘admin’.

Integration With Asynchronous Processing

Sometimes you may need asynchronous processes in these hooks. Here’s how it’s done with promises:

User.afterValidate('asyncValidationProcessing', async (user, options) => {
 await someAsyncFunction(user);
});

User.addHook('validationFailed', async (instance, options, error) => {
 await anotherAsyncFunction(instance, error);
});

Conclusion

Implementing the afterValidate and validationFailed hooks in Sequelize.js can enhance your application’s data integrity checks and error handling. These hooks provide a robust component to your validation logic, whether performing additional validations, custom error recovery, or asynchronous operations related to your model’s data.

By understanding and utilizing these hooks, you gain more control over your model lifecycle and ensure that your application’s data adheres strictly to the rules defined in your model validations. Remember, while hooks can be powerful, they should also be used judiciously to maintain clear and comprehensible code.

Next Article: How to Backup and Restore a Database in Sequelize.js

Previous Article: What is Eager Loading in Sequelize.js?

Series: Sequelize.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates