MAGAZINE
ルーターマガジン
Ruby の ORM、Sequel と ActiveRecord どっちを使うか
先に結論
- Rails アプリなら ActiveRecord。Rails 8 標準の Solid Queue / Solid Cache / Solid Cable も ActiveRecord 前提で、外すメリットが小さい。
- Sinatra / Roda / 素の Ruby の軽い構成なら Sequel が有力。ただしチームが Active Record に慣れているなら ActiveRecord でも十分動く。
- 決め手は「Rails を使うか」「チームがどちらに慣れているか」「Rails に依存しないライブラリの保守リスクをどう見るか」の 3 点。
以下、コードで違いを確認します。
ORM(Object-Relational Mapping)とは
ORM は、テーブルの行を User のようなオブジェクトとして扱い、クエリを Ruby で書ける層です。複雑な集計や DB 固有のチューニングでは抽象化が邪魔になることもありますが、普通のアプリなら ORM を使うほうが楽です。
Ruby で主に使われる ORM は ActiveRecord と Sequel の 2 つです。ほかに ROM(rom-rb)などもあり、Hanami は ROM ベースの DB 層を使いますが、この記事では扱いません。
- ActiveRecord:Rails 標準の ORM。Rails を使うなら実質デフォルト。
- Sequel:Rails 非依存のデータベースツールキット。初期の作者は Sharon Rosner で、現在は Jeremy Evans がメンテナンスしている。Sinatra や Roda、素の Ruby スクリプトでよく使われる。
どちらも「Active Record パターン」(モデルがテーブル行を表し、CRUD もモデルが持つ)で使えますが、設計思想とエコシステムの大きさは違います。
思想の違い:全部入りか、必要な分だけ足すか
| 観点 | ActiveRecord | Sequel |
|---|---|---|
| 由来 | Rails のコンポーネントの一つ | Rails 非依存の独立 gem |
| 基本方針 | Convention over Configuration(規約重視、暗黙の動作が多め) | 明示的な設計。使う機能を選んで足す |
| レイヤー構成 | ORM 層のみ(内部で Arel を使うが意識することは少ない) | 低レベルの Dataset(クエリビルダ)+ 高レベルの Sequel::Model の 2 層 |
| 機能の有効化 | 標準でほぼ全部入り | プラグイン方式(plugin :validation_helpers のように必要な分だけ追加) |
Sequel の Dataset は SQL をオブジェクトとして表現する遅延評価のビルダーで、イミュータブルです(メソッドを呼ぶたびに新しい Dataset が返る)。Sequel::Model はその上の薄い層なので、ORM としても、素のクエリビルダとしても使えます。
モデル定義:似ているが、同じ挙動ではない
ActiveRecord
class Post < ApplicationRecord
belongs_to :author, class_name: "User"
has_many :comments, dependent: :destroy
validates :title, presence: true
validates :body, length: { minimum: 10 }
before_save :normalize_title
end
Sequel
class Post < Sequel::Model
plugin :validation_helpers
plugin :timestamps
plugin :association_dependencies
many_to_one :author, class: :User
one_to_many :comments
add_association_dependencies comments: :destroy
def validate
super
validates_presence :title
validates_min_length 10, :body
end
def before_save
normalize_title
super
end
end
(normalize_title は各自の実装を想定した例示用メソッドです)
見た目は近いですが、同じ挙動ではありません。
- ActiveRecord では
dependent: :destroyもcreated_at/updated_atの自動更新も標準です。Sequel はassociation_dependencies/timestampsプラグインが必要です。 - ActiveRecord の
belongs_toは、Rails の既定設定では関連先の存在を検証します。Sequel のmany_to_oneは検証しないので、必要ならvalidates_presence :author_idなどを自分で書きます。 - Sequel でもフックは発火します。違いは、使う機能を自分で選ぶので、何が有効かをコードから読み取りやすいことです。
複雑な SQL を書くとき
どちらも、生 SQL とクエリビルダを混ぜて書けます。ActiveRecord も Rails 7.1 以降は CTE 用の .with があり、以前ほど生 SQL に頼らなくて済みます。
window 関数を例にします。Sequel は Ruby のメソッドだけで書けます。
Post.dataset.select_all(:posts)
.select_append(Sequel.function(:row_number)
.over(partition: :author_id, order: :created_at)
.as(:rn))
ActiveRecord で同じことを書くなら、SQL 文字列を渡すのが手軽です。
Post.select("posts.*, row_number() OVER (PARTITION BY author_id ORDER BY created_at) AS rn")
ActiveRecord でも Arel を使えば Ruby のオブジェクトとして組み立てられますが、Arel は公式ガイドで前面に出ている API ではなく、記述は冗長になりがちです。どちらが読みやすいかは好みが分かれます。差は「SQL を Ruby のオブジェクトとして組み立てる道具が、標準で用意されているか」です。
生成される SQL は、ActiveRecord でも to_sql や explain、クエリログで確認できます。
それぞれの強みと弱み
ActiveRecord
強み
- Rails と標準で統合されている(ジェネレータ、
bin/rails console、Active Storage、Action Text、Rails 8 の Solid Queue / Cache / Cable など) - Devise など、ActiveRecord 前提の gem が多い(ORM に依存しない gem もあるので、使う gem ごとに確認する)
- STI、ポリモーフィック関連、複数 DB 接続(primary/replica 切替・水平シャーディング)が標準で使える
弱み
- コールバックやバリデーションが暗黙に発火するので、規模が大きくなると「どこで何が起きているか」を追いにくい
- 単体でも動く(
sinatra-activerecordなどの実績あり)が、ActiveSupport / ActiveModel に依存する - Rails のメジャーバージョンごとに非互換や非推奨対応がある(これは ORM というより Rails 全体の追従コスト)
Sequel
強み
- Rails なしで Sinatra・Roda・単発スクリプトから使える
- プラグイン方式で、有効な機能がコードから読み取りやすい
- Dataset がイミュータブルで、複雑な SQL を Ruby で組み立てやすい。eager loading の制御(
eager_graphなど)や、PostgreSQL 固有機能(配列・JSON など)の拡張も揃っている - 複数 DB 接続やシャーディングも
server_blockなどでサポートしている(ActiveRecord だけの強みではない)
弱み
- Rails 向け gem のうち、ActiveRecord 前提のもの(Devise など)は使えない。代替がある領域もある(認証なら同じ作者の Rodauth。Rails 向けには
rodauth-railsがある) - Rails 8 標準の Solid Queue などは ActiveRecord 前提なので、Rails で Sequel を使うと別途の工夫が要る
- scaffold のような雛形生成が薄い
- ActiveRecord に慣れたチームだと、
many_to_one/one_to_manyといった独自の命名に慣れる時間が要る
状況別の選び方
- Rails アプリ:ActiveRecord。Rails 標準の機能(Solid Queue など)も ActiveRecord 前提で、外すメリットが小さい。
- Sinatra / Roda / 素の Ruby の軽い API やツール:Sequel が有力。依存が少なく、Dataset も使いやすい。ただしチームが ActiveRecord に慣れているなら ActiveRecord でも普通に動く。
- 複雑な SQL を Ruby で組み立てたい:Sequel も候補。SQL 文字列で書くほうが読みやすいなら ActiveRecord のままでよく、先に
.withなどで足りるか確認する。 - 立ち上がりの速さ、学習コスト:ActiveRecord。チームの知識をそのまま使える。
おわりに
どちらも成熟していて、機能不足で困ることはほぼありません。Rails を使うか、チームの慣れ、そして保守体制をどう見るかの 3 点で決めれば、大きく外しません。
株式会社ルーター 長戸
CONTACT
お問い合わせ・ご依頼はこちらから