Railsの中間テーブルでつまずいた話|自動で作られないレコードの作成
はじめに
こんにちは。
プログラミングスクールで Ruby on Rails を主に学習している、りゅうという者です。
現在は卒業制作として Web アプリを作成しています。
その中で今回、中間テーブル を使う際に「中間テーブルのレコードも自分で作成しなければならない」という点を学んだので、記事にまとめました。
⚠️ 注意事項
プログラミング初心者のため、内容に誤りがある可能性があります。
また、お使いの PC や開発環境によっては動作しない場合があります。
お気付きの点がありましたら、ぜひコメントなどで教えていただけると嬉しいです。
どうぞよろしくお願いいたします。
🧩 使用環境(バージョン情報)
| ツール | バージョン |
|---|---|
| Ruby | 3.2.3 |
| Rails | 7.2.2.2 |
| PostgreSQL | 17.6 |
| 開発環境 | Docker |
記事の内容
投稿のレコードを一覧で表示するまでの流れになっています。
最初のコード
↓
エラー
↓
原因の特定
↓
変更したコード
↓
結果
最初のコード
以下のように書いて、@proverbレコードを作成と取得、画面の表示を行おうとしています
def create
@proverb = current_user.proverbs.build(proverb_params)
if @proverb.save
redirect_to root_path, notice: "ことわざを登録しました。"
else
render :new, status: :unprocessable_entity
end
end
def index
@proverbs = Proverb.includes(proverb_contributors: :user)
.order(created_at: :desc)
end
<div class="bg-rose-100 h-full py-12 px-8">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8">
<% @proverbs.each do |proverb| %>
<div class="bg-white rounded-xl shadow-md p-4 flex flex-col items-center justify-between">
<!-- ユーザー情報 -->
<% proverb.proverb_contributors.each do |proverb_contributor| %>
<%= proverb_contributor.user.name %>
<% end %>
<!-- ことわざタイトル -->
<div class="border rounded-xl px-4 py-3 text-center w-full font-medium text-gray-900">
<%= proverb.title %>
</div>
</div>
<% end %>
</div>
</div>
(proverb_contributors: :user)
こう書くのは、proverb_contributors対userが多対1だからです
エラー
開発画面で確認するとユーザー名が表示されていません

原因の特定
コンソールで確認します
myapp(dev)> p = Proverb.last
Proverb Load (1.0ms) SELECT "proverbs".* FROM "proverbs" ORDER BY "proverbs"."id" DESC LIMIT $1 [["LIMIT", 1]]
=>
#<Proverb:0x0000ffffb65a47e8
...
myapp(dev)> p
=>
#<Proverb:0x0000ffffb65a47e8
id: 10,
word1: "絵の具",
word2: "星",
title: "わかめの勇気、ライオンの心",
meaning: "わかめの勇気、ライオンの心",
example: "わかめの勇気、ライオンの心",
status: "completed",
room_id: nil,
created_at: "2025-10-08 02:48:26.732776000 +0000",
updated_at: "2025-10-08 02:48:26.732776000 +0000">
myapp(dev)>
myapp(dev)>
myapp(dev)>
myapp(dev)> pcs = p.proverb_contributors
enum :role, {:solo=>0, :word_provider=>1, :proverb_maker=>2}
(called from <class:ProverbContributor> at /myapp/app/models/proverb_contributor.rb:5)
ProverbContributor Load (0.4ms) SELECT "proverb_contributors".* FROM "proverb_contributors" WHERE "proverb_contributors"."proverb_id" = $1 /* loading for pp */ LIMIT $2 [["proverb_id", 10], ["LIMIT", 11]]
=> []
コンソールで確認すると中間テーブルがないことが確認できます
変更したコード
中間テーブルのレコードがないことで表示ができないことがわかったので、中間テーブルのレコードを作成するコードに変更していきます
app/controllers/proverb_cotributor.rbのcreateメソッドを変更していきます
def create
# 失敗した時にロールバックするためにトランザクションを使用
ActiveRecord::Base.transaction do
@proverb = Proverb.new(proverb_params)
@proverb.save!
@proverb.proverb_contributors.create!(user: current_user, role: :solo)
end
redirect_to root_path, notice: "ことわざを登録しました。"
rescue ActiveRecord::RecordInvalid
render :new, status: :unprocessable_entity
end
!はfalseではなく、例外を返します。
例外はtransactionブロック外まで伝播するので、
rescueでこの例外を受け取れます。
結果
コンソールで確認していきます
myapp(dev)> p = Proverb.last
Proverb Load (1.4ms) SELECT "proverbs".* FROM "proverbs" ORDER BY "proverbs"."id" DESC LIMIT $1 [["LIMIT", 1]]
=>
#<Proverb:0x0000ffffb7e02088
...
myapp(dev)> p
=>
#<Proverb:0x0000ffffb7e02088
id: 11,
word1: "絵の具",
word2: "トンビ",
title: "わかめの勇気、ライオンの心",
meaning: "わかめの勇気、ライオンの心",
example: "わかめの勇気、ライオンの心",
status: "completed",
room_id: nil,
created_at: "2025-10-08 02:58:38.566107000 +0000",
updated_at: "2025-10-08 02:58:38.566107000 +0000">
myapp(dev)> pcs = p.proverb_contributors
ProverbContributor Load (1.9ms) SELECT "proverb_contributors".* FROM "proverb_contributors" WHERE "proverb_contributors"."proverb_id" = $1 /* loading for pp */ LIMIT $2 [["proverb_id", 11], ["LIMIT", 11]]
=>
[#<ProverbContributor:0x0000ffffb6880ac0
...
myapp(dev)> pcs
ProverbContributor Load (1.2ms) SELECT "proverb_contributors".* FROM "proverb_contributors" WHERE "proverb_contributors"."proverb_id" = $1 /* loading for pp */ LIMIT $2 [["proverb_id", 11], ["LIMIT", 11]]
=>
[#<ProverbContributor:0x0000ffffbcbc8358
id: 2,
user_id: 2,
proverb_id: 11,
created_at: "2025-10-08 02:58:38.588930000 +0000",
updated_at: "2025-10-08 02:58:38.588930000 +0000",
role: "solo">]
proverb_contributorという中間テーブルのレコードもしっかりできているのが確認できます
画面を見にいきます

しっかりユーザー名が表示されていますね。
まとめ
今回は中間テーブルのレコードも作成することを理解しました。考えれば当たり前なのですが、自動的にレコードが作られる訳ではないのですね。投稿とユーザーに中間テーブルを作ったのは初めてなので、勉強になりました。
間違えやもっと良い方法があったら教えて欲しいです。
よろしくお願いします🙇♀️
参考になった記事
最後に
noteで卒業制作の過程を書いています。
よかったら見てください!
Discussion