Defining Models

CQL Active Record models are Crystal classes or structs that map directly to database tables. Each model encapsulates the table's columns as properties, provides type-safe access to data, and includes methods for persistence, querying, and associations.


Basic Model Definition

To define a model, include the CQL::ActiveRecord::Model module with your primary key type and specify the database context:

# src/models/user.cr
require "cql"

class User
  # Include Active Record functionality with the primary key type
  include CQL::ActiveRecord::Model(Int32)

  # Map to the 'users' table in the specified database context
  db_context UserDB, :users

  # Define properties for each column
  property id : Int32?           # Primary key, nullable if auto-generated
  property name : String
  property email : String
  property age : Int32 = 0       # Default value
  property password : String?    # Nullable field
  property created_at : Time?    # Timestamp columns
  property updated_at : Time?

  # Constructor for creating new instances
  def initialize(@name : String, @email : String, @age : Int32 = 0, @password : String? = nil)
  end
end

Key Points:

  • Use class or struct for models (both are supported)

  • include CQL::ActiveRecord::Model(PkType) provides all Active Record functionality

  • The type parameter specifies the primary key type (e.g., Int32, Int64, UUID, ULID)

  • db_context DatabaseSchema, :table_name links the model to a specific table

  • Use property for each database column

  • Nullable types (e.g., Int32?, String?) are used for columns that may be NULL or auto-generated

  • Define a constructor to initialize required fields


Primary Key Types

CQL supports multiple primary key types to fit different application needs:

Integer Primary Keys

UUID Primary Keys

ULID Primary Keys


Working with Attributes

Individual Attribute Access

Access and modify attributes using the generated getter and setter methods:

Accessing All Attributes as a Hash

Use the attributes method to get a hash of all attribute values:

Mass Assignment

Set multiple attributes at once using the attributes method:

Important Notes:

  • Mass assignment only updates the instance in memory - call save to persist changes

  • Invalid attribute names are ignored silently

  • Attributes with incorrect types are ignored silently

  • Only existing model properties can be set

Handling Nullable Fields

For nullable database columns, use nullable Crystal types:


Database Fields Configuration

Ignoring Fields from Database Mapping

Use the @[DB::Field(ignore: true)] annotation for fields that shouldn't be persisted:


Complete Model Example

Here's a comprehensive example showing all common patterns:


Best Practices

  • Use appropriate types: Match Crystal types to your database column types

  • Make auto-generated fields nullable: Primary keys and timestamps should be nullable (Int32?, Time?)

  • Provide constructors: Define constructors for required fields to ensure valid object creation

  • Use @[DB::Field(ignore: true)]: For computed fields or temporary values that shouldn't be persisted

  • Be careful with mass assignment: Validate input when using attributes method with user data

  • Follow naming conventions: Use snake_case for database columns and property names


For more information on working with CQL Active Record models, see these related guides:

Model Operations:

Data Validation and Integrity:

Relationships:

Advanced Features:


Model Definition Methods

CQL provides several class methods for working with model definitions and metadata. These methods are available on all models that include CQL::ActiveRecord::Model.

Database Context Methods

db_context(schema, table)

Associates a model with a specific database schema and table:

schema

Returns the schema associated with the model:

table

Returns the table name for the model:

adapter

Returns the database adapter for the model's schema:

Table Metadata Methods

table_columns

Returns a hash of all table columns and their definitions:

table_column(column_name)

Returns the column expression for a specific column:

Object Creation Methods

build(**fields)

Creates a new model instance with the given attributes (alias for new):

Practical Examples

Inspecting Model Metadata

Using Build Method for Factories

Dynamic Model Information

Multi-Database Setup

Best Practices

Consistent Naming

  • Use descriptive model class names that match your domain

  • Follow Crystal naming conventions (PascalCase for classes)

  • Use plural table names (:users, :products, :order_items)

Database Context Organization

Metadata Inspection for Development


These model definition methods provide powerful introspection capabilities and help you work dynamically with your models while maintaining type safety. They're particularly useful for building developer tools, debugging, and creating flexible application architectures.

Last updated

Was this helpful?