Soft Deletes

CQL Active Record provides comprehensive soft delete functionality through the SoftDeletable module, which implements "paranoid" deletion behavior similar to Rails' acts_as_paranoid gem.

Overview

Soft deletes allow you to mark records as deleted without actually removing them from the database. This is useful for:

  • Data recovery: Accidentally deleted records can be restored

  • Audit trails: Maintain complete history of all records

  • Compliance: Meet regulatory requirements for data retention

  • Referential integrity: Avoid orphaned records in related tables

Basic Setup

1. Database Schema

First, ensure your table includes a deleted_at timestamp column:

AppDB = CQL::Schema.define(
  :app_database,
  adapter: CQL::Adapter::SQLite,
  uri: "sqlite3://app.db"
) do
  table :users do
    primary :id, Int32
    column :name, String
    column :email, String
    column :deleted_at, Time, null: true  # Required for soft deletes
    timestamps
  end
end

2. Model Definition

Include the SoftDeletable module in your Active Record model:

Core Features

Automatic Filtering

Once SoftDeletable is included, all queries automatically exclude soft-deleted records:

Soft Delete Operations

Instance Methods

Class Methods

Scopes

with_deleted

Include soft-deleted records in queries:

only_deleted

Query only soft-deleted records:

Counting Methods

Query Integration

Soft delete filtering integrates seamlessly with all query methods:

Advanced Usage

Checking Model Configuration

Custom Queries

The where_not_nil method is available for custom queries:

Callback Integration

Soft deletes work with Active Record callbacks:

Best Practices

1. Database Indexes

Add indexes on deleted_at for better query performance:

2. Regular Cleanup

Consider implementing a cleanup job for old soft-deleted records:

3. Testing

Test both active and deleted record scenarios:

4. Documentation

Always document which models use soft deletes in your API documentation:

Migration from Hard Deletes

If you're adding soft deletes to an existing model:

  1. Add the deleted_at column:

  1. Include the SoftDeletable module in your model

  2. Update any direct SQL queries to account for soft deletes

  3. Test thoroughly to ensure existing functionality isn't broken

Limitations

  • Performance: Queries become slightly more complex due to additional WHERE clauses

  • Storage: Deleted records continue to consume storage space

  • Unique constraints: Soft-deleted records may interfere with uniqueness constraints

  • Relationships: Related models need careful handling of soft-deleted associations

Last updated

Was this helpful?