Rails Engineering Handbook

Purpose

Ruby on Rails is a web application framework that emphasizes convention over configuration, developer productivity and elegant code.

This handbook defines the principles, standards and patterns for building Rails applications within this organization.

It builds upon the Engineering Fundamentals Handbook and Software Architecture Handbook, applying their principles to the Rails context.

Scope

This handbook covers:

This document focuses on enduring Rails principles rather than version-specific features. For version-specific guidance, see the Rails References.

Rails Philosophy

Convention over Configuration

Rails provides sensible defaults for every aspect of application structure, naming and behaviour.

Engineers should follow Rails conventions unless there is a clear, documented reason to deviate. Conventions reduce decision fatigue, make code predictable and enable developers to move between projects quickly.

Don't Repeat Yourself (DRY)

Every piece of knowledge should have a single, unambiguous representation within the system.

Duplication increases maintenance cost and creates opportunities for inconsistency. When modifying behaviour, every duplicated location must be updated — a process that is error-prone and容易遗漏.

MVC Architecture

Rails follows the Model-View-Controller architectural pattern.

LayerResponsibility
ModelBusiness logic, data validation, persistence.
ViewPresentation logic, user interface rendering.
ControllerRequest handling, parameter parsing, response generation.

Controllers should be thin. Models should capture domain logic. Views should contain minimal logic.

Principles

Thin Controllers

Controllers should only orchestrate: parse parameters, invoke business logic, and render responses.

Business logic belongs in models, service objects or other domain classes — not in controllers.

A controller action should typically be three to five lines.

Fat Models, but Not Too Fat

Models naturally become the default home for business logic.

However, when a model exceeds a reasonable size, extract cohesive groups of behaviour into separate classes: service objects, value objects, policy objects or form objects.

A model that grows beyond a few hundred lines is a signal that responsibilities should be extracted.

Keep the View Dumb

Views should contain minimal logic.

Logic in views is hard to test, hard to maintain and easy to overlook during refactoring.

Use presenters, decorators or view objects for presentation logic. Use helpers sparingly and only for view-level formatting.

Prefer Service Objects for Complex Operations

When an operation involves multiple models, external services or complex orchestration, extract it into a service object.

A service object:

Database as a Detail

Rails' ActiveRecord pattern makes the database feel like an invisible part of the application.

Resist this abstraction. Design database schema deliberately. Understand query performance. Use migrations to evolve schema incrementally.

Code Organization

Application Structure

Follow Rails defaults for the standard directories. Custom code belongs in app* with clear naming.

app*
  controllers/
  models/
  views/
  services/       # Service objects
  forms/          # Form objects
  policies/       # Authorization policies
  presenters/     # View presentation logic
  serializers/    # JSON serialization
  values/         # Value objects
  queries/        # Query objects

Naming Conventions

Follow Rails naming conventions consistently.

ConceptConventionExample
ModelSingular, CamelCaseUserAccount
TablePlural, snake_caseuser_accounts
ControllerPlural, CamelCase with ControllerUserAccountsController
ServiceNamed after operationRegisterUser
MigrationDescriptive snake_caseadd_email_to_users

Standards

Models

Migrations

Routes

API Development

Testing

Testing Philosophy

Test Distribution

Follow the testing principles in the Testing Strategies Guide.

For Rails specifically:

Test TypeWhat to TestSpeed
Model specsValidations, associations, scopes.Fast
Request specsController behaviour, status codes,Moderate
response format.
Feature specsCritical user journeys.Slow
Unit testsService objects, form objects,Fast
presenters.

Patterns

Service Objects

Use service objects to encapsulate complex operations.

class RegisterUser
  def initialize(params)
    @params = params
  end

  def call
    # Business logic here
  end
end

Form Objects

Use form objects to encapsulate form validation and data processing for complex forms that do not map directly to a single model.

Query Objects

Use query objects to encapsulate complex database queries that do not belong in a model scope.

Policy Objects

Use policy objects to encapsulate authorization logic.

Anti-patterns

Fat Controllers

Controllers that exceed five to ten lines per action indicate that business logic needs to be extracted.

Callback Overuse

ActiveRecord callbacks (after_save, before_update) create implicit dependencies that make code hard to reason about and test.

Prefer explicit service objects over callbacks for side effects.

Magic Strings

Hard-coded values, status strings and configuration constants embedded in business logic should be extracted into constants, enums or configuration classes.

Skipping Tests

Every non-trivial feature or fix should include tests.

Skipping tests creates technical debt that accumulates through unexpected regressions and reduced confidence in changes.

Decision Frameworks

When to Use a Service Object

Use a service object when:

When to Introduce a Gem

Before adding a gem, ask:

  1. What problem does this gem solve?
  2. Could we solve it with a simple class?
  3. Is the gem well-maintained and documented?
  4. Does the gem add unnecessary complexity?
  5. Is the gem compatible with our Rails version?

Prefer a simple custom implementation over a heavyweight gem for small concerns.

AI Integration

AI assistants can assist with Rails development through:

When using AI for Rails development, provide:

See the AI Engineering Handbook for general AI workflow guidance.

AI-Assisted Upgrades

The Ruby Upgrade Toolkit is a Claude Code plugin that fully automates Ruby and Rails version upgrades. It follows a phased methodology — audit, plan, fix, verify — with three workflow modes:

See the Rails Upgrade Playbook for the detailed workflow and usage guide.

Capability Map

This handbook is the entry point for the Rails Engineering capability. The following documents form the complete capability:

Handbooks

Glossaries

Guides

Playbooks

Checklists

Templates

Learning Paths

References

AI Workflows

Related Documents