Open-Source Wikis

/

Ruby on Rails

/

Ruby on Rails

/

Architecture

rails/rails

Architecture

Rails is structured as a set of loosely coupled gems that plug into a shared boot process. This page describes how the pieces fit together: the component map, the request lifecycle, and the application boot sequence.

Component map

graph TD
    AS[Active Support<br/>core_ext, cache, notifications]
    AM[Active Model<br/>validations, callbacks, dirty]
    AR[Active Record<br/>ORM, connection adapters]
    AP[Action Pack<br/>routing + controllers]
    AV[Action View<br/>templates, helpers]
    AMail[Action Mailer]
    AMbox[Action Mailbox]
    AJob[Active Job]
    AC[Action Cable]
    AStor[Active Storage]
    AT[Action Text]
    RT[Railties<br/>CLI, generators, boot]

    AS --> AM
    AS --> AR
    AS --> AP
    AS --> AV
    AS --> AJob
    AS --> AC
    AM --> AR
    AP --> AV
    AP --> AMail
    AR --> AStor
    AJob --> AStor
    AStor --> AT
    AR --> AMbox
    AJob --> AMbox
    RT --> AS
    RT --> AP
    RT --> AR
    RT --> AV

Active Support is at the bottom: every other component depends on it. Active Model layers model concerns on top, and Active Record adds database persistence. Action Pack and Action View handle HTTP and rendering. Active Job, Active Storage, Action Mailer, Action Mailbox, Action Cable, and Action Text sit at higher levels and rely on the layers below them. Railties orchestrates everything via railties and engines.

Component dependencies

You can see the dependency chain by reading each gem's *.gemspec:

  • actionpack/actionpack.gemspec depends on activesupport, actionview, rack, etc.
  • activerecord/activerecord.gemspec depends on activesupport, activemodel.
  • activestorage/activestorage.gemspec depends on activerecord, activejob, actionpack.
  • actiontext/actiontext.gemspec depends on activerecord, activestorage, actionpack.
  • railties/railties.gemspec depends on activesupport, actionpack, actionview, plus thor.

The top-level rails.gemspec lists every component at the same version and pins them together for a release.

The MVC request lifecycle

A typical HTTP request flows through several layers:

sequenceDiagram
    participant Browser
    participant Rack
    participant Middleware as Middleware stack
    participant Router as ActionDispatch::Routing
    participant Controller as ActionController
    participant Model as ActiveRecord
    participant View as ActionView
    Browser->>Rack: HTTP request
    Rack->>Middleware: env hash
    Middleware->>Router: env after middlewares
    Router->>Controller: dispatch to controller#action
    Controller->>Model: query / mutate
    Model-->>Controller: records
    Controller->>View: render template
    View-->>Controller: HTML / JSON
    Controller-->>Middleware: response
    Middleware-->>Rack: response
    Rack-->>Browser: HTTP response

The middleware stack lives in actionpack/lib/action_dispatch/middleware/ and is configured by railties/lib/rails/application/default_middleware_stack.rb. The router (actionpack/lib/action_dispatch/routing/route_set.rb) maps a URL to a controller action, the controller manipulates models and renders a view, and the response bubbles back through the stack.

For more detail, see features/request-lifecycle.

Application boot

When you run bin/rails server or bin/rails console, the boot sequence is documented in railties/lib/rails/application.rb:

graph TD
    A[require 'config/boot.rb'] --> B[require Rails framework]
    B --> C[Define Rails.application class]
    C --> D[before_configuration callbacks]
    D --> E[Load config/environments/ENV.rb]
    E --> F[before_initialize callbacks]
    F --> G[Run Railtie initializers]
    G --> H[Run application initializers]
    H --> I[Build middleware stack]
    I --> J[to_prepare callbacks]
    J --> K[before_eager_load + eager_load!]
    K --> L[after_initialize callbacks]
    L --> M[App ready]

Each component (Active Record, Action Mailer, etc.) hooks into boot via a Railtie subclass — see railties/lib/rails/railtie.rb. The app's config/application.rb extends Rails::Application, which itself extends Rails::Engine. See features/initialization-and-railties for a deeper walk-through.

Plugin extension points

Rails is extensible at several layers:

  • Railties — the canonical extension point. Subclassing Rails::Railtie lets a gem register initializers, generators, Rake tasks, and notifications subscribers.
  • Engines — full mini-applications that ship their own routes, models, and views. Rails::Engine is the base class; Rails::Application itself inherits from it.
  • Connection adapters — Active Record's ActiveRecord::ConnectionAdapters::AbstractAdapter lets third parties add database backends (the built-in ones are mysql2, trilogy, postgresql, sqlite3).
  • Queue adaptersActiveJob::QueueAdapters::AbstractAdapter lets gems plug Sidekiq, Resque, etc. into Active Job.
  • Storage servicesActiveStorage::Service is the base class for Disk, S3, GCS, Azure, and Mirror.
  • Mailbox ingresses — Action Mailbox accepts mail from Postmark, Mailgun, SendGrid, Postfix, and others through HTTP-or-pipe ingress controllers in actionmailbox/app/controllers/action_mailbox/ingresses/.
  • Subscription adapters — Action Cable's ActionCable::SubscriptionAdapter::Base (e.g., redis, postgresql, async).

Filesystem layout

rails/
├── activesupport/        # Bottom of the stack; everything depends on this
├── activemodel/          # Validations + callbacks for plain Ruby objects
├── activerecord/         # ORM
├── actionpack/           # Routing + ActionController + ActionDispatch
├── actionview/           # Templates + helpers
├── actionmailer/         # Outgoing email
├── actionmailbox/        # Inbound email
├── activejob/            # Background jobs
├── actioncable/          # WebSockets
├── activestorage/        # File uploads
├── actiontext/           # Rich text
├── railties/             # CLI, generators, application boot
├── guides/               # Source of guides.rubyonrails.org
├── tools/                # Test runner, releaser, lint glue
├── tasks/                # Top-level Rake tasks
├── .github/              # CI workflows, issue templates
├── Gemfile               # Dev/test dependencies for the whole monorepo
├── Gemfile.lock
└── rails.gemspec         # Top-level meta-gem

Each component directory follows the same shape: lib/ (production code), test/ (Minitest), bin/test (component-level test runner), CHANGELOG.md, README.{md,rdoc}, and a gemspec.

Cross-cutting infrastructure

A few utilities are shared across every component:

  • ActiveSupport::Notifications — a publish/subscribe bus used for instrumentation. Each component publishes its own events (sql.active_record, process_action.action_controller, etc.) — see activesupport/lib/active_support/notifications/.
  • ActiveSupport::Concern — the standard way to package a module of methods, callbacks, and class methods together (activesupport/lib/active_support/concern.rb).
  • ActiveSupport::Autoload — Zeitwerk-based autoload registration used throughout (activesupport/lib/active_support/dependencies/autoload.rb).
  • Deprecators — every component owns a Deprecator instance (e.g., ActiveRecord.deprecator) so each can deprecate independently.
  • Log subscribers + structured event subscribers — every component has log_subscriber.rb and structured_event_subscriber.rb that translate notifications into log lines.

For a deep dive, see packages/active-support.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Ruby on Rails wiki | Factory