Active Record Design pattern is one of the design patterns used in Domain Driven Design. This pattern encapsulates the database and business logic implementation, and group them together, usually in a class, that developers can create. This pattern is mostly familiar in Object Oriented Programming due to its structure.

Benefits of Active Record Pattern

  • Combines data and behaviour into a single object
  • Simplifies CRUD operations, making it quick to implement
  • Keeps business logic close to data it operates on

When to use it

  • Small applications
  • You build simple CRUD apps
  • Your app and your database are very similar
  • You focus on Rapid development

When should you avoid it

  • Your app is not a typical CRUD app and has complex business logic that do not map to database tables
  • When your classes are bloated with loads of methods
  • Large scale apps
  • Microservices
  • When your database schema changes frequently

Example

In the example below, a Database operation has been encapsulated in a User class and provides methods, such as save, delete, findById and findAll and all of them interact with database.

import { PrismaClient } from '@prisma/client';  
  
const prisma = new PrismaClient();  
  
export class User {  
  id: number;  
  name: string;  
  email: string;  
  
  constructor(name: string, email: string, id?: number) {  
    this.name = name;  
    this.email = email;  
    this.id = id || 0;  
  }  
  
  async save(): Promise<User> {  
    if (this.id === 0) {  
      const user = await prisma.user.create({  
        data: {  
          name: this.name,  
          email: this.email,  
        },  
      });  
      this.id = user.id;  
      return this;  
    } else {  
      await prisma.user.update({  
        where: { id: this.id },  
        data: {  
          name: this.name,  
          email: this.email,  
        },  
      });  
      return this;  
    }  
  }  
  
  static async findById(id: number): Promise<User | null> {  
    const user = await prisma.user.findUnique({ where: { id } });  
    if (!user) return null;  
    return new User(user.name, user.email, user.id);  
  }  
  
  static async findAll(): Promise<User[]> {  
    const users = await prisma.user.findMany();  
    return users.map(u => new User(u.name, u.email, u.id));  
  }  
  
  async delete(): Promise<void> {  
    if (this.id !== 0) {  
      await prisma.user.delete({ where: { id: this.id } });  
    }  
  }  
}