Design Patterns

The Active Record pattern is the primary pattern used in CQL. Understanding it helps you write better models and make informed architectural decisions.

What is Active Record?

Active Record is a design pattern where an object wraps a row in a database table, encapsulating both the data and the database access logic.

In Active Record:

  • A model class represents a database table

  • A model instance represents a row in that table

  • The model knows how to save itself

  • Business logic lives inside the model

Active Record in CQL

struct User
  include CQL::ActiveRecord::Model(Int64)
  db_context MyDB, :users

  property id : Int64?
  property name : String
  property email : String
  property active : Bool = true

  # Business logic in the model
  def activate!
    @active = true
    save
  end

  def deactivate!
    @active = false
    save
  end
end

# Usage - the model handles its own persistence
user = User.new("John", "john@example.com")
user.save      # Model saves itself
user.activate! # Business logic + persistence together

Key Characteristics

1. Self-Aware Persistence

Models know how to persist themselves:

2. Class Methods for Queries

The model class provides query methods:

3. Built-in Validations

Validation logic lives in the model:

4. Lifecycle Callbacks

Models respond to persistence events:

Benefits

Simplicity

Active Record is intuitive. The code reads naturally:

Rapid Development

Everything you need is in one place:

Discoverability

Looking at a model tells you everything about that entity: its data, validations, relationships, and behavior.

Trade-offs

Coupling

Active Record couples your domain logic to the database structure. Changes to the database schema may require changes to business logic.

Testing

Models are harder to test in isolation because they depend on the database.

Complexity

For complex domains, models can become bloated with too much logic.

When Active Record Works Best

  • CRUD-heavy applications

  • Rapid prototyping

  • Small to medium applications

  • When database schema closely matches domain model

When to Consider Alternatives

  • Complex business logic

  • Multiple data sources

  • Need for database-agnostic domain

  • Heavy testing requirements

Comparison with Other Patterns

Pattern
Data
Persistence Logic
Business Logic

Active Record

In model

In model

In model

Repository

In model

In repository

In model

Data Mapper

In entity

In mapper

In entity

Example: Complex Active Record Model

This model:

  • Defines data (properties)

  • Handles its own persistence (save, validations)

  • Contains business logic (pay!, ship!)

  • Manages relationships (belongs_to, has_many)

  • Responds to lifecycle events (callbacks)

All in one cohesive unit - that's the Active Record pattern.

Last updated

Was this helpful?