【Ruby on Rails】ActiveRecordの基本:モデルとCRUD操作

Ruby

こんにちは、かつコーチです。

Railsでデータを扱おうとすると、Post.createPost.find といったコードを目にします。

SQLを書いていないのに、なぜデータベースを操作できるのか。

最初は不思議に感じるところだと思います。

この記事では、Railsのデータベース操作を支えるActiveRecordORM:Object-Relational Mapping、Rubyのオブジェクトとデータベースのテーブルを対応づける仕組みです)の基本と、create / find / update / destroy という基本操作(CRUD:Create・Read・Update・Deleteの頭文字です)を解説します。

読み終えるころには、モデルを使ったデータ操作に自信が持てるようになっているはずです。

ActiveRecordとは何か(ORMの説明)

テーブルとモデルが1対1で対応する

ActiveRecordの最大の特徴は、データベースのテーブルとRubyのクラス(モデル)が自動的に対応づけられることです。

例えば posts テーブルがあれば、Post モデルが自動的にそのテーブルを操作できるようになります。

# app/models/post.rb
class Post < ApplicationRecord
end

このクラスにはメソッドを1つも書いていませんが、titlebody といったカラムに対応するメソッドが自動的に使えるようになります。

これは、テーブルの構造(カラム名や型)をActiveRecordが実行時に読み取り、それに応じたメソッドを動的に用意してくれるためです。

SQLを書かずに操作できる理由

先ほどのマイグレーションで作成した posts テーブルに対して、以下のようにRubyのコードだけでデータを操作できます。

# rails consoleでの実行例
Post.create(title: "初めての投稿", body: "ActiveRecordを学び中です")

このコードは、裏側で以下のようなSQLに変換されて実行されています。

INSERT INTO posts (title, body, created_at, updated_at)
VALUES ('初めての投稿', 'ActiveRecordを学び中です', '2026-08-22 01:00:00', '2026-08-22 01:00:00');

SQLを直接書く必要がないので、データベースの方言(MySQLとPostgreSQLの文法の違いなど)を意識せずにコードを書けるのがActiveRecordの大きなメリットです。

create/find/update/destroyの基本

Create:データを作成する

# 方法1:createで作成と保存を同時に行う
post = Post.create(title: "Railsの学習記録", body: "今日はActiveRecordを学んだ")

# 方法2:newで組み立ててからsaveで保存する
post = Post.new(title: "Railsの学習記録", body: "今日はActiveRecordを学んだ")
post.save

create は「組み立て」と「保存」を1回で行い、new + save は2段階に分けて行います。

バリデーション(データの妥当性チェック)でエラーになる可能性がある場合は、new + save の形で、保存前にデータを加工したいケースに向いています。

Read:データを取得する

# 全件取得
posts = Post.all

# IDを指定して1件取得(見つからないと例外が発生する)
post = Post.find(1)

# 条件を指定して1件取得(見つからなければnilが返る)
post = Post.find_by(title: "Railsの学習記録")

# 条件を指定して複数件取得
posts = Post.where(published: true)

# 並び替え
posts = Post.order(created_at: :desc)

findfind_by の挙動の違いは、初心者がよく混同するポイントです。

find はIDで検索し、見つからなければエラーになります。

find_by は条件で検索し、見つからなくても nil を返すだけで、エラーにはなりません。

Update:データを更新する

post = Post.find(1)
post.update(title: "更新後のタイトル")

update メソッドは、値の書き換えと保存を同時に行います。

複数の属性を同時に変更したいときも、ハッシュでまとめて渡せます。

post.update(title: "新タイトル", body: "新しい本文")

Destroy:データを削除する

post = Post.find(1)
post.destroy

destroy を呼ぶと、対象のレコードがデータベースから削除されます。

コントローラの destroy アクションでは、この処理を呼び出すのが定番の形です。

# app/controllers/posts_controller.rb
def destroy
  @post = Post.find(params[:id])
  @post.destroy
  redirect_to posts_path, notice: "投稿を削除しました。", status: :see_other
end

よくあるつまずきポイント・エラー対処

ActiveRecord::RecordNotFound でアプリが落ちる

私が実際にやってしまった失敗です。

存在しないIDを find で検索したときに、エラー画面がそのままユーザーに表示されてしまいました。

ActiveRecord::RecordNotFound in PostsController#show
Couldn't find Post with 'id'=999

❌ Before:findの例外を考慮していない

# app/controllers/posts_controller.rb
def show
  @post = Post.find(params[:id])
end

存在しないIDでアクセスされると、この時点で例外が発生し、そのままエラー画面になってしまいます。

✅ After:rescue_fromで例外を捕捉し、わかりやすい画面に誘導する

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :render_not_found

  private

  def render_not_found
    redirect_to root_path, alert: "指定されたデータが見つかりませんでした。"
  end
end

find は「必ず見つかる前提」の操作なので、見つからない可能性がある場面では、例外処理をセットで用意しておくことが大切です。

saveの戻り値を確認せずに次の処理に進んでしまう

save はバリデーションに失敗すると false を返しますが、例外は発生しません。

これに気づかずハマったことがあります。

❌ Before:saveの結果を確認せず、常に成功したものとして扱う

def create
  @post = Post.new(post_params)
  @post.save
  redirect_to @post, notice: "投稿を作成しました。"
end

バリデーションエラーで保存に失敗しても、この書き方だと @post.save の結果を無視しているため、@post にIDが振られておらず、redirect_to @post の時点でエラーになってしまいます。

✅ After:saveの戻り値を条件分岐で確認する

def create
  @post = Post.new(post_params)
  if @post.save
    redirect_to @post, notice: "投稿を作成しました。"
  else
    render :new, status: :unprocessable_entity
  end
end

save は成功・失敗を表す真偽値を返す設計になっているので、必ず条件分岐で受け止める習慣をつけましょう。

save!(末尾に ! がついたメソッド)を使うと、失敗時に例外を発生させることもできます。

用途に応じて使い分けてください。

まとめ

この記事のポイント

  • ActiveRecordは、テーブルとRubyのクラス(モデル)を自動的に対応づけるORM
  • SQLを直接書かなくても、Rubyのメソッドでデータベースを操作できる
  • create は組み立てと保存を同時に行い、new + save は2段階に分けて行う
  • find はIDで検索して見つからなければ例外、find_by は条件検索でnilを返す
  • save の戻り値は必ず確認し、失敗時の処理も用意しておく

次に読むべき記事

  • マイグレーションの基本:テーブルを作成・変更する
  • バリデーションの基本
  • アソシエーション(has_many・belongs_to)の書き方

タグ: Ruby on Rails, 初心者向け, データベース

タイトルとURLをコピーしました