Active Record(アクティブレコード)とは?Railsを支える設計パターンと基本を実例で解説
Active Record(アクティブレコード)という言葉は2つの意味で使われます。1つはMartin Fowlerが整理した「データベースの1行を1つのオブジェクトとして扱う」設計パターン、もう1つはその考え方をRuby on Railsが実装したライブラリ(O/Rマッパー)です。この記事では両者を切り分けたうえで、モデル定義とCRUD、バリデーション・アソシエーション・scopeなどの主要機能、ActiveRecord::BaseとApplicationRecordの違い、そしてFat ModelやN+1問題といった実務でつまずく弱点までを実例で解説します。
まとめ:Active Recordの要点
- Active Recordは「テーブルの1行=1つのオブジェクト」で対応づける設計パターン(Martin Fowlerが2002年の著書で定義)。RailsのActive Recordはその代表的な実装。
- クラスがテーブルに、インスタンスが行に、属性がカラムに対応する。命名規約に従えばSQLを書かずにCRUDできる。
- 主要機能はバリデーション、アソシエーション、クエリ(
where・scope)、コールバックの4つ。 ActiveRecord::Baseは全モデルの祖先クラス、ApplicationRecordはRails 5.0以降に追加された共通の基底クラス。モデルは後者を継承する。- DB永続化を伴わないモデル機能(フォームオブジェクトの検証など)は
ActiveModelが担う。 - 弱点はモデルが肥大化するFat Modelと、関連取得で発行クエリが増えるN+1問題。設計の分離と
includesで対処する。
以下では、まず「パターンとしてのActive Record」と「Railsの実装」を切り分けてから、基本操作と主要機能、周辺クラス、弱点の順に見ていきます。
Active Recordとは何か:設計パターンとRailsの実装
混乱の元は、同じ「Active Record」が抽象的な設計パターンと具体的なRailsのライブラリの両方を指す点にあります。先にこの2層を分けておくと、以降の話が整理しやすくなります。
設計パターンとしてのActive Record
Active Recordパターンは、Martin Fowlerが著書『Patterns of Enterprise Application Architecture』(2002年)で名前を付けた、データベースアクセスの定石です。定義はシンプルで、テーブルの1行を1つのオブジェクトに対応させ、そのオブジェクト自身がデータの読み書き(永続化)ロジックを持つというもの。データとデータ操作が同じクラスに同居するため、直感的に書ける反面、後述するFat Modelの温床にもなります。Ruby以外でもPHPのLaravel EloquentやYiiのActive Recordなど、多くのフレームワークがこのパターンを採用しています。
RailsにおけるActive Record(O/Rマッパー)
RailsのActive Recordは、このパターンをRubyで実装したO/Rマッパーで、MVCの「M(モデル)」を担います。特徴は設定より規約(Convention over Configuration)で、命名規約に従うだけで対応関係が自動で決まります。たとえばUserクラスは複数形のusersテーブルに、idカラムが主キーに自動で結び付きます。
| Rubyの世界 | データベースの世界 |
|---|---|
モデルクラス(User) |
テーブル(users) |
インスタンス(1つのuser) |
行(1レコード) |
属性(user.name) |
カラム(name) |
この対応づけにより、開発者はSQLではなくRubyのメソッド呼び出しでデータを扱えます。Railsをこれから触る場合の準備はruby on rails を vscode で開発する環境構築【2026年版】にまとめています。
Active Recordの基本的な使い方:モデル定義とCRUD
Active Recordの最小構成は「モデルクラスの定義」と「テーブルの作成」です。ここが揃えば、あとはメソッドでレコードを操作できます。
モデルの作成とマイグレーション
モデルとテーブルは、ジェネレータとマイグレーションで作ります。rails generate model でモデルクラスとマイグレーションファイルが生成され、rails db:migrate で実際のテーブルが作られます。
rails generate model User name:string email:string
rails db:migrate
生成されるマイグレーションは、テーブル定義をRubyで表したものです。バージョン番号(下記の[8.1])は使用中のRailsに合わせて自動で入ります。
class CreateUsers < ActiveRecord::Migration[8.1]
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
コマンドの詳しいオプションはRailsジェネレータ(rails generate)の使い方で解説しています。
CRUD操作の基本
テーブルができれば、生成・取得・更新・削除(CRUD)はすべてモデル経由で書けます。SQLは一行も書きません。
# 生成(Create)
user = User.create(name: "John Doe", email: "[email protected]")
# 取得(Read)
user = User.find_by(email: "[email protected]")
# 更新(Update)
user.update(name: "Johnny Doe")
# 削除(Delete)
user.destroy
findは主キー、find_byは任意の条件で1件を返します。存在しないとfindは例外、find_byはnilを返す、という挙動の違いが実務では効いてきます。
Active Recordの主要機能
Active Recordが単なるSQLの置き換えにとどまらないのは、モデルに宣言的な機能を持たせられるからです。実務で使う頻度が高いのは次の4つです。
バリデーション(validates)
保存前にデータの妥当性を検査する仕組みです。validatesで宣言し、save時に自動で走ります。検査に通らなければ保存されず、errorsに理由が入ります。
class User < ApplicationRecord
validates :name, presence: true
validates :email, presence: true, uniqueness: true
end
この例は「名前は必須」「メールは必須かつ重複不可」を保証します。DB制約と違いアプリ側で検査するため、エラーメッセージを画面に返しやすいのが利点です。
アソシエーション(has_many / belongs_to)
テーブル間の関連をモデル上で宣言する機能です。has_manyとbelongs_toで1対多を表すと、外部キーを意識せずに関連レコードをたどれます。
class User < ApplicationRecord
has_many :posts
end
class Post < ApplicationRecord
belongs_to :user
end
user.posts # そのユーザーの投稿一覧
post.user # その投稿の書き手
1対多・多対多・中間テーブルの扱いなど関連の種類ごとの書き方は、RailsのAssociationとは?で体系的に整理しています。
クエリとscope(where・order・ActiveRecord::Relation)
検索条件はメソッドをつなげて組み立てます。whereやorderの戻り値はActiveRecord::Relationというオブジェクトで、実際にDBへ問い合わせるのは結果が必要になった瞬間まで遅延されます。そのため条件を何段でも連結でき、1回のSQLにまとまります。
active_users = User.where(active: true).order(created_at: :desc)
テーブルをまたいで絞り込むときはjoinsで関連を結合できます。よく使う条件はscopeとして名前を付けておくと再利用できます。名前が付くことで意図も読み取りやすくなります。
class User < ApplicationRecord
scope :active, -> { where(active: true) }
scope :recent, -> { where("created_at > ?", 1.month.ago) }
end
User.active.recent # スコープを連結できる
コールバック(before_save など)
レコードのライフサイクル(保存・作成・削除など)の前後に処理を差し込む仕組みです。保存直前の正規化などに使います。
class User < ApplicationRecord
before_save :normalize_email
private
def normalize_email
self.email = email.downcase
end
end
便利な反面、暗黙の副作用が増えて挙動を追いにくくなりやすいため、テストしづらい重い処理はコールバックに載せない、という判断が後半で述べるFat Model対策につながります。
ActiveRecord::BaseとApplicationRecordの違い
モデルを継承させる親クラスには2つの名前が出てきて、初学者がつまずきやすい箇所です。結論から言うと、継承の順序が違うだけで役割は地続きです。
Rails 4.2までは、すべてのモデルがActiveRecord::Baseを直接継承していました。Rails 5.0(2016年)からは、間にApplicationRecordという共通クラスが1枚挟まる形に変わりました。rails new時にapp/models/application_record.rbが自動生成され、中身は次のようになっています。
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
abstract_class = trueはテーブルを持たない抽象クラスであることを示します。この1枚があることで、全モデル共通の設定やメソッドを1か所に集約できるのが導入の狙いです。ActiveRecord::Baseを直接いじるとgemやRails本体まで影響しますが、ApplicationRecordへの変更は自分のアプリのモデルだけに閉じます。現行のRailsでは、モデルはApplicationRecordを継承すると覚えておけば十分です。
Active RecordとActiveModelの違い
ActiveModelは、データベースを伴わないモデル機能を提供するモジュール群です。Active Recordが「DB+モデル機能」なのに対し、ActiveModelは「モデル機能だけ」を切り出したもの、と捉えると整理できます。
| 観点 | Active Record | ActiveModel |
|---|---|---|
| DBテーブル | 必要(永続化する) | 不要(永続化しない) |
| 主な用途 | DBに保存するモデル | フォームオブジェクト・APIパラメータの検証 |
| 使える機能 | 検証・関連・クエリ・コールバック等 | 検証・属性・コールバック等 |
たとえば複数モデルにまたがる入力を1つにまとめるフォームオブジェクトは、テーブルを持たないのでActiveModel::Modelを取り込んで作ります。
class SignupForm
include ActiveModel::Model
attr_accessor :name, :email
validates :name, presence: true
validates :email, presence: true
end
これで、DBに保存しないオブジェクトにもActive Recordと同じ検証を効かせられます。
Active Recordパターンの弱点と使いどころ
Active Recordは書きやすさが最大の武器ですが、その書きやすさゆえに設計が崩れやすい面もあります。ここは公式ガイドではあまり踏み込まれない実務側の論点なので、判断軸まで示します。
Fat Model問題
データ操作もビジネスロジックもモデルに書けてしまうため、放置するとモデルが数百行に膨れ上がります。これがFat Model(太ったモデル)です。対処は責務ごとの分離で、共通の関心事はConcern、複雑な業務手順はサービスオブジェクト、入力の集約はフォームオブジェクトへ逃がします。設計の指針としてはRuby on RailsとDRY原則の考え方が実務の判断基準になります。
N+1問題
関連レコードをループ内でたどると、1件ごとにSQLが飛び、1回+N回のクエリが発行されます。これがN+1問題で、一覧画面が遅くなる典型原因です。関連をまとめて先読みするincludesを使えば、クエリは2回程度に収まります。
# 悪い例:ユーザー数だけ追加クエリが飛ぶ
User.all.each { |u| puts u.posts.size }
# 良い例:関連を先読みしてクエリを削減
User.includes(:posts).each { |u| puts u.posts.size }
Active Recordは書きやすさゆえにN+1を見落としやすいので、一覧系の実装では発行SQLをログで確認する習慣を持つと安全です。
Active Recordを選ぶべきでない場面
Active Recordが不利になるのは、ドメインモデルの設計とDBスキーマを独立させたい場合です。レコードとオブジェクトが1対1で癒着するため、複雑なドメイン駆動設計(DDD)や、テーブル構造に縛られないモデルを作りたい大規模開発では窮屈になります。そうした要件では、永続化ロジックを別クラスに分離するData Mapperパターン(Rubyのrom-rb、JavaのHibernate等)が向きます。逆に、CRUDが中心の一般的なWebアプリでは、Active Recordの生産性が明確に上回ります。まずはActive Recordで始め、DBとドメインの乖離が痛みになった時点でData Mapperを検討する、という順序が現実的です。
よくある質問(FAQ)
「アクティブレコード」とは何を指しますか?
データベースの1行(レコード)を1つのオブジェクトとして能動的(active)に扱い、そのオブジェクト自身がデータの読み書きを担う設計パターンを指します。名称はMartin Fowlerが著書で命名したものです。日常の会話では、この設計パターンをRubyで実装したRailsのライブラリを指して「Active Record」と呼ぶことも多く、文脈で使い分けられています。
ActiveRecordとActiveModelの違いは何ですか?
データベースへの永続化を伴うかどうかが違いです。Active Recordはテーブルと結び付き、保存・検索・更新・削除を行います。ActiveModelはテーブルを持たず、検証・属性・コールバックといったモデル機能だけを提供します。DBに保存しないフォームオブジェクトやAPIパラメータの検証にはActiveModelを使い、DBに保存するデータにはActive Recordを使います。
ApplicationRecordとActiveRecord::Baseはどう違いますか?
継承の順序が異なります。Rails 4.2まではモデルがActiveRecord::Baseを直接継承していましたが、Rails 5.0以降はActiveRecord::Baseを継承したApplicationRecordを、各モデルが継承する形になりました。全モデル共通の設定をApplicationRecordの1か所に書けるのが利点で、現行のRailsではモデルはApplicationRecordを継承します。
Ruby以外の言語でもActive Recordは使えますか?
使えます。Active Recordはあくまで設計パターンなので、多くの言語・フレームワークに実装があります。PHPではLaravelのEloquentやYiiのActive Recordなど、他にもさまざまな言語で同名パターンの実装が提供されています。RailsのActive Recordはその中で最も広く知られた実装の1つ、という位置づけです。
Active RecordパターンとData Mapperパターンの違いは?
データ操作ロジックをどこに置くかが違います。Active Recordはレコードを表すオブジェクト自身が永続化ロジックを持ちます。Data Mapperはオブジェクトと永続化を別クラス(マッパー)に分離し、ドメインモデルをDBスキーマから独立させます。手軽さならActive Record、ドメイン設計の自由度と大規模での保守性ならData Mapperが向きます。