【Rails/DB入門】中間テーブルって何?『多対多』を制する者はリレーションを制す!
はじめに
こんにちは!Railsやデータベースの学習、順調ですか? 「フォロー機能」や「いいね機能」、「タグ付け機能」を作ろうとしたとき、テーブル同士の関係(リレーション)で頭を悩ませた経験はありませんか?
-
「一人のユーザーは、たくさんの投稿に『いいね』できる」
-
「一つの投稿は、たくさんのユーザーから『いいね』される」
このような、お互いが「たくさん」を持つ関係を多対多(many-to-many) と呼びます。 この記事では、この『多対多』を華麗に解決してくれる中間テーブルという考え方を、世界一わかりやすく解説します!
なぜ必要なの?『多対多』の壁 🤔
SNSアプリを例に考えてみましょう。 まず、ユーザー情報を保存する users テーブルと、投稿を保存する posts テーブルがあります。
users テーブル
| id | name |
|---|---|
| 1 | 田中さん |
| 2 | 鈴木さん |
posts テーブル
| id | content |
|---|---|
| 101 | 今日のランチ 🍝 |
| 102 | 猫がかわいい 🐈 |
ここに「いいね」機能を追加したい!…でも、どうやって「誰が」「どの投稿に」いいねしたかを記録すればいいのでしょう?
失敗例①:posts テーブルに user_id を入れる
| id | content | liked_by_user_id |
|---|---|---|
| 101 | 今日のランチ 🍝 | 1 (田中さん) |
| 102 | 猫がかわいい 🐈 | ??? |
これでは、1つの投稿に1人しか「いいね」できません。鈴木さんが「いいね」したら、田中さんの記録が消えてしまいます。
失敗例②:users テーブルに post_id を入れる
| id | name | liked_post_id |
|---|---|---|
| 1 | 田中さん | 101 |
| 2 | 鈴木さん | ??? |
これでは、1人のユーザーは1つの投稿にしか「いいね」できません。田中さんが他の投稿に「いいね」したら、前の記録が消えてしまいます。
困りました。 このように、多対多の関係は、2つのテーブルを直接つなぐだけでは表現できないのです。
救世主、その名は『中間テーブル』✨
この問題を解決してくれるのが、**中間テーブル(Join Table)**です。 今回は「いいね」なので、likes という名前の中間テーブルを作ってみましょう。
中間テーブルの仕事はたった一つ。2つのテーブルの「関係」だけを記録することです。
likes 中間テーブル
| id | user_id (誰が) | post_id (どの投稿に) |
|---|---|---|
| 1 | 1 (田中さん) | 101 |
| 2 | 1 (田中さん) | 102 |
| 3 | 2 (鈴木さん) | 101 |
users テーブルと posts テーブルの間に、この likes テーブルを置くだけ。 たったこれだけで、複雑だった関係がスッキリ整理できました。
-
1行目: 田中さん (
user_id: 1) が、投稿No.101 (post_id: 101) に「いいね」したことを示します。 -
2行目: 田中さんは、投稿No.102 (
post_id: 102) にも「いいね」しています。 -
3行目: 鈴木さん (
user_id: 2) は、投稿No.101 (post_id: 101) に「いいね」しています。
これで、1人が複数の投稿に「いいね」できますし、1つの投稿が複数人から「いいね」されることも、矛盾なく記録できるようになりました!
まとめ:中間テーブルは『関係』の記録係 📖
中間テーブルとは、 多対多の関係にある2つのテーブルの間に立ち、その「関係性」だけを記録するためだけのシンプルなテーブル のことです。
ユーザー情報や投稿内容そのものではなく、「AとBはつながっている」という事実だけを淡々と記録する、名簿や対応表のような存在だとイメージしてください。
この考え方は、様々な機能で応用されています。
-
ユーザー 🤝 ユーザー の「フォロー機能」(
relationshipsテーブル) -
投稿 🤝 タグ の「タグ付け機能」(
post_tagsテーブル) -
商品 🤝 注文 の「注文明細」(
order_detailsテーブル)
中間テーブルを理解すれば、作れるアプリケーションの幅がぐっと広がります。 リレーションを制して、開発をもっと楽しんでいきましょう!