RailsでのRDB設計の書き方と考え方(1対多など)
RDB設計とは
リレーショナルデータベースの構造を定義するものです。
この記事では「一対一」「一対多」「多対多」のリレーションの具体例、書き方を解説します。
モデルの書き方
具体的にどう書いていくのか説明していきます。
Userと一対多の関係
1人のユーザーと一対多の関係を書いていきます。
例えば日報なら1人のユーザーは日報を複数投稿します。
このように1人に対して複数のものが存在するのが一対多の関係です。
1.ユーザーと日報
・モデル
日報(Daily Report)の一対多の関係を考える場合、例えば、1つのユーザーが複数の日報を持つといったケースがあります。以下は、これを実現するための例です。
class DailyReport < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :daily_reports
end
上記のコードでは、Userモデルは複数のDailyReportを持つ関係を示すhas_manyを使用し、逆にDailyReportモデルは1つのUserに属することを示すbelongs_toを使用しています。
- マイグレーション:
DailyReportモデルのマイグレーションファイルで、user_idを格納するための外部キーを追加します。Userモデルの中身も見ていきます。
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :slack_id
t.string :slack_name
t.datetime :deleted_at, default: nil
t.timestamps
end
end
end
class CreateDailyReports < ActiveRecord::Migration[7.0]
def change
create_table :daily_reports do |t|
t.references :user, null: false, foreign_key: true
#他のカラムも追加できる
t.timestamps
end
end
end
これを他の具体例も見ながら書いていきます。
2.ブログ記事とコメント:
一つのブログ記事(BlogPost)に対して、複数のコメント(Comment)が存在します。これは、一つのブログ記事が複数の読者からコメントを受けるよくある例です。
class BlogPost < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :blog_post
end
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
class CreateBlogPosts < ActiveRecord::Migration[6.0]
def change
create_table :blog_posts do |t|
t.string :title
t.text :content
t.timestamps
end
end
end
3.ユーザーと投稿:
一人のユーザー(User)が複数の投稿(Post)を持つ場合。これは、一つのユーザーが複数のコンテンツを作成できるよくある例です。
class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
end
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
class CreatePosts < ActiveRecord::Migration[6.0]
def change
create_table :posts do |t|
t.string :title
t.text :content
t.references :user, foreign_key: true
t.timestamps
end
end
end
1対1
1対1の関係も具体的に見ていきます。
1.部署と責任者
一つの部署を一人の責任者が管理している場合です。
class Department < ActiveRecord::Base
has_one :head
end
class Head < ActiveRecord::Base
belongs_to :department
end
class CreateDepartments < ActiveRecord::Migration[6.0]
def change
create_table :departments do |t|
t.string :name
t.timestamps
end
end
end
class CreateHeads < ActiveRecord::Migration[6.0]
def change
create_table :heads do |t|
t.string :name
t.references :department, foreign_key: true, unique: true
t.timestamps
end
end
end
2.プロジェクトとリーダー
各プロジェクトの中にリーダーが1人いる場合です。
class Project < ActiveRecord::Base
has_one :leader
end
class Leader < ActiveRecord::Base
belongs_to :project
end
class CreateProjects < ActiveRecord::Migration[6.0]
def change
create_table :projects do |t|
t.string :name
t.timestamps
end
end
end
class CreateLeaders < ActiveRecord::Migration[6.0]
def change
create_table :leaders do |t|
t.string :name
t.references :project, foreign_key: true, unique: true
t.timestamps
end
end
end
多対多
1人のユーザーは複数のプロジェクトに参加でき、同時に1つのプロジェクトには複数のユーザーが関わっていることを想定します。下のコードはUserモデルとProjectモデルが多対多の関係です。
class User < ActiveRecord::Base
has_many :project_memberships
has_many :projects, through: :project_memberships
end
class Project < ActiveRecord::Base
has_many :project_memberships
has_many :users, through: :project_memberships
end
class ProjectMembership < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
中間のProjectMembershipモデルを関連付けして、
has_many :throughを使用して、ユーザーとプロジェクトの多対多の関係ができています。
以下がマイグレーションファイルの例です。
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
class CreateProjects < ActiveRecord::Migration[6.0]
def change
create_table :projects do |t|
t.string :name
t.timestamps
end
end
end
class CreateProjectMemberships < ActiveRecord::Migration[6.0]
def change
create_table :project_memberships do |t|
t.references :user, foreign_key: true
t.references :project, foreign_key: true
t.timestamps
end
end
end
それ以外の関係
-
多対1(Many-to-One)
例えば複数の商品が
例えば、複数の商品が1つのカテゴリに属している場合などです。 -
1対0または多対0(One-to-Zero or Many-to-Zero)
顧客が注文を持っているが、すべての顧客が注文を持っているわけではない時です。 -
多対1(Many-to-One)
学生とクラスの関係で1人の学生が複数のクラスに在籍する場合です。
DB設計の有益記事
Discussion