--- name: 37signals-rails description: 37signals Rails coding principles and conventions from DHH, Jorge Manrubia, and the Fizzy/Basecamp/HEY codebase. This skill should be used when writing, reviewing, or refactoring Ruby on Rails code following the 37signals philosophy — vanilla Rails, CRUD controllers, rich domain models, concerns, no service objects, Hotwire, Turbo, Stimulus, Solid Queue, Solid Cache, Solid Cable, multi-tenancy, Minitest, custom auth, or DHH conventions. --- # 37signals Rails Best Practices Comprehensive coding principles and conventions for Ruby on Rails applications, as practiced at 37signals (Basecamp, HEY, Fizzy). Contains 56 rules across 8 categories, prioritized by architectural impact. Derived from official 37signals sources: the Fizzy codebase, STYLE.md, AGENTS.md, the Rails Doctrine, DHH's "On Writing Software Well" series, and the unofficial 37signals style guide (265 Fizzy PRs). ## When to Apply Reference these guidelines when: - Writing new Rails controllers, models, or views - Deciding between gems and vanilla Rails - Modeling state and database schema - Setting up background jobs, caching, or real-time features - Reviewing code for 37signals-style conventions - Refactoring toward rich domain models - Choosing authentication or authorization approach - Adding Stimulus controllers or Turbo patterns ## Rule Categories by Priority | Priority | Category | Impact | Prefix | |----------|----------|--------|--------| | 1 | Architecture Fundamentals | CRITICAL | `arch-` | | 2 | Controllers & REST | CRITICAL | `ctrl-` | | 3 | Domain Modeling | HIGH | `model-` | | 4 | State Management | HIGH | `state-` | | 5 | Database & Infrastructure | HIGH | `db-` | | 6 | Views & Frontend | MEDIUM | `view-` | | 7 | Code Style | MEDIUM | `style-` | | 8 | Testing | MEDIUM | `test-` | ## Quick Reference ### 1. Architecture Fundamentals (CRITICAL) - [`arch-rich-models`](references/arch-rich-models.md) - Rich Domain Models Over Service Objects - [`arch-vanilla-rails`](references/arch-vanilla-rails.md) - Vanilla Rails is Plenty - [`arch-avoid-patterns`](references/arch-avoid-patterns.md) - Deliberately Avoided Patterns and Gems - [`arch-earn-abstractions`](references/arch-earn-abstractions.md) - Earn Abstractions Through Rule of Three - [`arch-build-before-gems`](references/arch-build-before-gems.md) - Build It Yourself Before Reaching for Gems - [`arch-ship-to-learn`](references/arch-ship-to-learn.md) - Start Simple — Add Complexity Only After Validation - [`arch-domain-facades`](references/arch-domain-facades.md) - Domain Models as Facades Over Internal Complexity - [`arch-single-business-layer`](references/arch-single-business-layer.md) - Single Layer for Business Logic - [`arch-custom-auth`](references/arch-custom-auth.md) - Custom Passwordless Auth Over Devise ### 2. Controllers & REST (CRITICAL) - [`ctrl-crud-only`](references/ctrl-crud-only.md) - CRUD Controllers Over Custom Actions - [`ctrl-model-as-resources`](references/ctrl-model-as-resources.md) - Model Non-CRUD Operations as Separate Resources - [`ctrl-thin-controllers`](references/ctrl-thin-controllers.md) - Thin Controllers with Rich Domain Models - [`ctrl-params-expect`](references/ctrl-params-expect.md) - Use params.expect() for Parameter Validation - [`ctrl-controller-concerns`](references/ctrl-controller-concerns.md) - Controller Concerns for Cross-Cutting Behavior - [`ctrl-nested-resources`](references/ctrl-nested-resources.md) - Nested Resources with scope module ### 3. Domain Modeling (HIGH) - [`model-concerns`](references/model-concerns.md) - Concerns for Horizontal Code Sharing - [`model-normalizes`](references/model-normalizes.md) - Use normalizes Macro for Data Cleaning - [`model-store-accessor`](references/model-store-accessor.md) - Use store_accessor for JSON Column Access - [`model-delegated-type`](references/model-delegated-type.md) - Use delegated_type for Polymorphism - [`model-counter-caches`](references/model-counter-caches.md) - Counter Caches to Prevent N+1 Count Queries - [`model-touch-chains`](references/model-touch-chains.md) - Touch Chains for Cache Invalidation - [`model-callbacks-auxiliary`](references/model-callbacks-auxiliary.md) - Callbacks for Auxiliary Complexity - [`model-event-tracking`](references/model-event-tracking.md) - Polymorphic Event Model for Activity Tracking - [`model-poro-namespacing`](references/model-poro-namespacing.md) - Namespace POROs Under Parent Models ### 4. State Management (HIGH) - [`state-records-over-booleans`](references/state-records-over-booleans.md) - Records as State Over Boolean Columns - [`state-timestamps`](references/state-timestamps.md) - Timestamps for State Transitions - [`state-enums`](references/state-enums.md) - Enums for Categorical States - [`state-db-constraints`](references/state-db-constraints.md) - Database Constraints Over ActiveRecord Validations - [`state-write-time`](references/state-write-time.md) - Compute at Write Time Not Read Time ### 5. Database & Infrastructure (HIGH) - [`db-backed-everything`](references/db-backed-everything.md) - Database-Backed Everything - [`db-solid-queue`](references/db-solid-queue.md) - Solid Queue for Background Jobs - [`db-solid-cable`](references/db-solid-cable.md) - Solid Cable for Real-Time Pub/Sub - [`db-solid-cache`](references/db-solid-cache.md) - Solid Cache for Application Caching - [`db-multi-tenancy`](references/db-multi-tenancy.md) - Path-Based Multi-Tenancy with Current.account - [`db-uuid-primary-keys`](references/db-uuid-primary-keys.md) - UUIDs as Primary Keys - [`db-no-foreign-keys`](references/db-no-foreign-keys.md) - No Foreign Key Constraints ### 6. Views & Frontend (MEDIUM) - [`view-turbo-frames`](references/view-turbo-frames.md) - Turbo Frames for Scoped Page Fragments - [`view-turbo-streams`](references/view-turbo-streams.md) - Turbo Streams for Real-Time Updates - [`view-stimulus-targets`](references/view-stimulus-targets.md) - Stimulus Targets Over CSS Selectors - [`view-stimulus-design`](references/view-stimulus-design.md) - Stimulus Controller Design Principles - [`view-helpers-not-partials`](references/view-helpers-not-partials.md) - Extract Logic to Helpers Not Partials - [`view-progressive-enhancement`](references/view-progressive-enhancement.md) - Progressive Enhancement as Primary Pattern - [`view-fragment-caching`](references/view-fragment-caching.md) - Fragment Caching for View Performance - [`view-http-caching`](references/view-http-caching.md) - HTTP Caching with fresh_when and ETags ### 7. Code Style (MEDIUM) - [`style-conditionals`](references/style-conditionals.md) - Expanded Conditionals Over Guard Clauses - [`style-method-ordering`](references/style-method-ordering.md) - Methods Ordered by Call Sequence - [`style-positive-names`](references/style-positive-names.md) - Use Positive Names for Methods and Scopes - [`style-naming-return-values`](references/style-naming-return-values.md) - Method Names Reflect Return Values - [`style-visibility-modifiers`](references/style-visibility-modifiers.md) - Visibility Modifier Formatting - [`style-bang-methods`](references/style-bang-methods.md) - Bang Methods Only When Non-Bang Exists - [`style-async-naming`](references/style-async-naming.md) - Use _later and _now Suffixes for Async Operations ### 8. Testing (MEDIUM) - [`test-minitest`](references/test-minitest.md) - Minitest Over RSpec - [`test-fixtures`](references/test-fixtures.md) - Database Fixtures Over FactoryBot - [`test-no-damage`](references/test-no-damage.md) - No Test-Induced Design Damage - [`test-no-system-tests`](references/test-no-system-tests.md) - Integration Tests Over System Tests - [`test-behavior`](references/test-behavior.md) - Test Behavior Not Implementation ## How to Use Read individual reference files for detailed explanations and code examples: - [Section definitions](references/_sections.md) - Category structure and impact levels - [Rule template](assets/templates/_template.md) - Template for adding new rules ## Reference Files | File | Description | |------|-------------| | [references/_sections.md](references/_sections.md) | Category definitions and ordering | | [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules | | [metadata.json](metadata.json) | Version and reference information |