rails/rails
Active Record
Active contributors: rafaelfranca, byroot, kamipo, eileencodes
Purpose
Active Record is Rails' ORM. It maps database rows to Ruby objects, provides a lazy chainable query DSL, and ships connection adapters for SQLite, PostgreSQL, MySQL (via mysql2 and trilogy). It is the largest component in the framework — about 70K lines of lib/ Ruby, roughly a third of the framework.
Source: activerecord/lib/active_record/ plus the Arel SQL AST library at activerecord/lib/arel/.
Directory layout
activerecord/
├── lib/
│ ├── active_record/
│ │ ├── base.rb # ActiveRecord::Base — the root class
│ │ ├── core.rb
│ │ ├── attributes.rb / attribute_methods/
│ │ ├── associations/ # has_many, belongs_to, has_one, through
│ │ ├── connection_adapters/ # SQLite, PostgreSQL, MySQL2, Trilogy
│ │ ├── connection_handling.rb
│ │ ├── database_configurations/ # config/database.yml parsing
│ │ ├── encryption/ # Encrypted attributes
│ │ ├── enum.rb
│ │ ├── fixtures.rb # Test fixtures
│ │ ├── future_result.rb # Async query support
│ │ ├── locking/ # Optimistic and pessimistic locking
│ │ ├── middleware/ # AR-specific Rack middleware
│ │ ├── migration/ # Schema migration DSL and runner
│ │ ├── persistence.rb / counter_cache.rb
│ │ ├── query_cache.rb / query_logs.rb
│ │ ├── relation/ # The query builder
│ │ ├── relation.rb
│ │ ├── scoping/ # default_scope, current_scope
│ │ ├── store.rb
│ │ ├── tasks/ # rake db:migrate, db:create, etc.
│ │ ├── testing/ # Parallel testing helpers
│ │ ├── transactions.rb
│ │ ├── translation.rb
│ │ ├── type/ # Type coercion (extends ActiveModel::Type)
│ │ ├── validations.rb
│ │ ├── version.rb / gem_version.rb
│ │ └── … # ~80 more top-level files
│ └── arel/ # SQL AST library
├── test/
│ ├── cases/ # Most of the suite
│ ├── fixtures/
│ ├── models/
│ └── schema/ # Test schema definitions
├── examples/
└── activerecord.gemspecKey abstractions
| Constant | File | Purpose |
|---|---|---|
ActiveRecord::Base |
activerecord/lib/active_record/base.rb |
Root class for all models |
ActiveRecord::Relation |
activerecord/lib/active_record/relation.rb |
Lazy, chainable query builder |
ActiveRecord::ConnectionAdapters::AbstractAdapter |
activerecord/lib/active_record/connection_adapters/abstract_adapter.rb |
Base class for all adapters |
ActiveRecord::ConnectionAdapters::*Adapter |
activerecord/lib/active_record/connection_adapters/{sqlite3,postgresql,mysql2,trilogy}_adapter.rb |
Concrete adapters |
ActiveRecord::SchemaCache |
activerecord/lib/active_record/connection_adapters/schema_cache.rb |
Cached column / index metadata |
ActiveRecord::Migration |
activerecord/lib/active_record/migration.rb |
DSL for schema changes |
ActiveRecord::QueryMethods |
activerecord/lib/active_record/relation/query_methods.rb |
where, order, joins, etc. |
ActiveRecord::Associations::* |
activerecord/lib/active_record/associations/ |
belongs_to / has_many / has_one |
ActiveRecord::Encryption |
activerecord/lib/active_record/encryption/ |
Encrypted attributes |
ActiveRecord::FutureResult |
activerecord/lib/active_record/future_result.rb |
Async query result |
ActiveRecord::Type::Value |
activerecord/lib/active_record/type/ |
Per-column type coercion (extends ActiveModel::Type) |
Arel::Nodes::* |
activerecord/lib/arel/nodes/ |
SQL expression tree |
How a query works
graph LR
A["User.where(name: 'Bob').limit(10)"] --> B[ActiveRecord::Relation]
B --> C[QueryMethods append where + limit]
C --> D[PredicateBuilder builds Arel nodes]
D --> E[Arel AST]
E --> F[ConnectionAdapter#to_sql]
F --> G[Database]
G --> H[Raw rows]
H --> I[Type::Value.deserialize per column]
I --> J[Model instances]Relation records where_clause, order_clause, limit, etc. as separate nodes (relation/where_clause.rb, relation/from_clause.rb). When the relation is iterated, connection.exec_query runs the SQL and the results are typed and constructed into model instances.
The ActiveRecord::Relation#async_* methods (async_count, async_load) return FutureResult objects that materialize on first access. The async pool lives in connection_adapters/async_query_executor integration with each adapter.
Connection adapters
activerecord/lib/active_record/connection_adapters/:
abstract/ # Shared building blocks
abstract_adapter.rb # Base class for all adapters
abstract_mysql_adapter.rb # Shared between mysql2 and trilogy
mysql/ # Type definitions, schema, statement
mysql2/ # mysql2-specific gem integration
mysql2_adapter.rb
trilogy/
trilogy_adapter.rb
postgresql/ # PG types (jsonb, hstore, array, range, ...)
postgresql_adapter.rb
sqlite3/
sqlite3_adapter.rb
column.rb, schema_cache.rb
pool_config.rb, pool_manager.rb
statement_pool.rbThe base class AbstractAdapter defines the contract. Each concrete adapter overrides:
connect,disconnect,reconnect- Schema introspection (
columns,tables,indexes,foreign_keys) - Schema mutation (
create_table,add_column, etc.) - Query execution (
exec_query,exec_insert,exec_update,exec_delete) - Transaction handling
- Type registration
Adding a new adapter means subclassing AbstractAdapter (or AbstractMysqlAdapter for a MySQL-compatible driver) and implementing the required methods. Tests live in activerecord/test/cases/adapters/<adapter>/.
Associations
Each association kind has its own builder under activerecord/lib/active_record/associations/:
belongs_to_association.rb(andbelongs_to_polymorphic_association.rb)has_one_association.rb/has_one_through_association.rbhas_many_association.rb/has_many_through_association.rbsingular_association.rb(shared between has_one and belongs_to)collection_association.rbandcollection_proxy.rb
The builder/ subdirectory contains macro implementations for belongs_to, has_many, etc. The preloader/ subdirectory implements N+1 prevention via eager loading.
Multiple databases
Configured via database.yml:
production:
primary:
database: app_production
primary_replica:
database: app_production
replica: trueCode in activerecord/lib/active_record/database_configurations/ parses the YAML, including the connections_for method that handles environments and inheritance. connection_handling.rb adds connects_to, connected_to, and while_preventing_writes. Sharding is supported via the shards: key on connects_to.
Encryption
activerecord/lib/active_record/encryption/ adds at-rest column encryption with deterministic and non-deterministic modes:
encrypted_attribute_type.rb— wraps any other type and encrypts on serialization.cipher.rb— AES-GCM encryption.key_provider.rb— pluggable key sources.derived_secret_key_provider.rb— derives keys fromRails.application.credentials.scheme.rb— encryption configuration per-attribute.
Public API: encrypts :ssn on a model. Documented in guides/source/active_record_encryption.md.
Migration
activerecord/lib/active_record/migration.rb plus the migration/ directory:
migration.rb— thechange/up/downDSL.migration/compatibility.rb— schema versioning so old migrations behave as expected on newer Rails.migration/command_recorder.rb— records reversible migrations.migration/default_strategy.rb,migration/execution_strategy.rb— strategy pattern around how DDL runs.
The runner is invoked by bin/rails db:migrate, implemented in activerecord/lib/active_record/tasks/database_tasks.rb.
Transactions and locking
activerecord/lib/active_record/transactions.rb— wrapsBase.transactionand instancesave/destroyin DB transactions.activerecord/lib/active_record/connection_adapters/abstract/transaction.rb— savepoint stack and lifecycle.activerecord/lib/active_record/locking/optimistic.rb—lock_versioncolumn.activerecord/lib/active_record/locking/pessimistic.rb—SELECT ... FOR UPDATE.
Integration points
- Railtie:
activerecord/lib/active_record/railtie.rbboots the connection pool, registers cache, and wires up middleware. - Active Model: Active Record includes
ActiveModel::Validations,Callbacks,Dirty,Naming,Translation. - Active Job:
ActiveRecord::DestroyAssociationAsyncJobrunsdependent: :destroy_async. - Active Storage / Action Text: both use
belongs_to :record, polymorphic: trueagainst host records. - Action Pack: controller params are converted to AR attributes via
ActiveModel::ForbiddenAttributesProtection(strong parameters integration).
Notable middleware
activerecord/lib/active_record/middleware/:
database_selector.rb— routes reads to a replica based on a resolver.shard_selector.rb— routes requests to a shard.query_logs.rb— tag SQL queries with controller / action / job comments.
Testing matrix
Run the suite against a specific adapter:
cd activerecord
bundle exec rake test:sqlite3
bundle exec rake test:postgresql
bundle exec rake test:mysql2
bundle exec rake test:trilogyConnection details come from activerecord/test/config.yml. The CI matrix runs all four.
Entry points for modification
- Adding a query method: add to
relation/query_methods.rband updaterelation.rb'sRelationwhitelist. - Adding a database type: subclass
ActiveRecord::Type::Value, register on the adapter (activerecord/lib/active_record/connection_adapters/<adapter>/type.rb). - Adding a connection adapter: subclass
AbstractAdapter(orAbstractMysqlAdapter); implementconnect, schema introspection,exec_query, types. Add a test config and atest:my_adapterrake task. - Adding a migration helper: add to
connection_adapters/abstract/schema_statements.rbor its database-specific subclasses, plus tests inactiverecord/test/cases/migration/.
Related pages
- packages/active-model — many ActiveRecord behaviors are inherited from here.
- packages/active-support — Notifications power
sql.active_recordevents. - features/request-lifecycle — how the connection pool ties into a request.
- reference/configuration — the
config.active_record.*options.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.