Ruby on Rails

Active Record(アクティブレコード)とは?Railsを支える設計パターンと基本を実例で解説

Active Record(アクティブレコード)という言葉は2つの意味で使われます。1つはMartin Fowlerが整理した「データベースの1行を1つのオブジェクトとして扱う」設計パターン、もう1つはその考え方をRuby on Railsが実装したライブラリ(O/Rマッパー)です。この記事では両者を切り分けたうえで、モデル定義とCRUD、バリデーション・アソシエーション・scopeなどの主要機能、ActiveRecord::BaseApplicationRecordの違い、そしてFat ModelやN+1問題といった実務でつまずく弱点までを実例で解説します。

まとめ:Active Recordの要点

  • Active Recordは「テーブルの1行=1つのオブジェクト」で対応づける設計パターン(Martin Fowlerが2002年の著書で定義)。RailsのActive Recordはその代表的な実装。
  • クラスがテーブルに、インスタンスが行に、属性がカラムに対応する。命名規約に従えばSQLを書かずにCRUDできる。
  • 主要機能はバリデーション、アソシエーション、クエリ(wherescope)、コールバックの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_bynilを返す、という挙動の違いが実務では効いてきます。

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_manybelongs_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)

検索条件はメソッドをつなげて組み立てます。whereorderの戻り値は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が向きます。

関連記事

資料請求

RELATED POSTS 関連記事