patterns

Keep Controllers Thin: Use Command Objects

Command objects (a.k.a. “actions”) make controllers boring. They’re easy to test, easy to instrument, and they produce a stable API for the rest of your app. This is the kind of structure that makes large Rails apps maintainable.

Composable “Policy Scope” without a Gem

Authorization libraries are great, but you can also build a lightweight policy scope. The key is to keep it composable: a single public method that returns an ActiveRecord::Relation and nothing else.

ActiveRecord::Relation as a Boundary (No Arrays)

Return relations from query objects, not arrays. It keeps composition possible (additional filters, pagination, eager loading) and avoids loading huge result sets accidentally.

Newtype pattern for type-safe primitives

The newtype pattern wraps a primitive in a tuple struct to create a distinct type. This prevents mixing up values that are semantically different but have the same underlying type (like UserId(u32) vs PostId(u32)). The compiler enforces that you can't

Avoid Callback Chains: Use Domain Events (In-App)

Callback chains become spooky action at a distance. A simple in-app event bus keeps side effects explicit and testable. This isn’t about Kafka—it’s about clarity and seams.

Compound components pattern for flexible APIs

Compound components create flexible, composable APIs by sharing state between parent and child components via context. Instead of passing dozens of props, child components access shared state through context. A Select component might have Select.Trigg

Django model soft delete pattern

Soft deletes mark records as deleted without removing them from the database. I add a deleted_at field and override the delete() method. A custom manager excludes soft-deleted records by default. I provide a hard_delete() method for permanent removal.

Query objects for complex ActiveRecord queries

When queries become too complex for scopes—involving multiple joins, subqueries, or raw SQL fragments—I extract them into dedicated query objects. Each query object is a plain Ruby class that encapsulates one specific query pattern and returns an Acti

Database design patterns and anti-patterns

Database design patterns solve recurring problems. I use the Repository pattern to abstract data access. Active Record maps objects to tables. Unit of Work tracks changes for batch commits. Identity Map caches loaded entities. The Specification patter

Type state pattern for compile-time state machines

The typestate pattern uses Rust's type system to encode state machines, making invalid states unrepresentable. Each state is a separate type, and transitions consume self and return a new state. The compiler prevents calling methods that aren't valid

Service-Level “Circuit Breaker” (Simple)

When a dependency is failing, you don’t want to keep hammering it. A simple circuit breaker trips after N failures and short-circuits for a cooldown window. It protects your app and your vendor.