質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

解決済

1回答

1039閲覧

Railsのモデルで多対多の記述の仕方が分からない

yosse95ai

総合スコア39

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

0クリップ

投稿2021/09/27 15:39

編集2021/09/27 23:33

前提・実現したいこと

以下のようなテーブルがあると想定した場合の、モデルを記述したいです。

イメージ説明
イメージ説明

artistは0個以上のsongを持ちます。
songcomposer_idlyricist_idは1人以上、arranger_idは0人以上のartistを持ちます。

この場合のモデルのhas_manybelongs_toの記述の仕方が分かりません。

artist.rbsong.rbに多対多の記述を追加したいと思っています。

該当のソースコード

該当のモデルです。

ruby

1# app/models/artist.rb 2 3class Artist < ApplicationRecord 4end

ruby

1# app/models/song.rb 2 3class Song < ApplicationRecord 4end

外部キーの指定の仕方があっているのかわかりませんが、マイグレーションは以下のようにしました。

ruby

1# db/migrate/20210927135753_create_songs.rb 2 3class CreateSongs < ActiveRecord::Migration[6.1] 4 def change 5 create_table :songs do |t| 6 t.string :song_name 7 t.references :lyricist 8 t.references :composer 9 t.references :arranger 10 11 t.timestamps 12 end 13 add_foreign_key :songs, :artists, column: :lyricist_id 14 add_foreign_key :songs, :artists, column: :composer_id 15 add_foreign_key :songs, :artists, column: :arranger_id 16 end 17end

マイグレート後のスキーマです。

ruby

1# db/schema.rb 2 3ActiveRecord::Schema.define(version: 2021_09_27_135753) do 4 5 # These are extensions that must be enabled in order to support this database 6 enable_extension "plpgsql" 7 8 create_table "artists", force: :cascade do |t| 9 t.string "artist_name", null: false 10 t.datetime "created_at", precision: 6, null: false 11 t.datetime "updated_at", precision: 6, null: false 12 end 13 14 create_table "songs", force: :cascade do |t| 15 t.string "song_name" 16 t.bigint "lyricist_id" 17 t.bigint "composer_id" 18 t.bigint "arranger_id" 19 t.datetime "created_at", precision: 6, null: false 20 t.datetime "updated_at", precision: 6, null: false 21 t.index ["arranger_id"], name: "index_songs_on_arranger_id" 22 t.index ["composer_id"], name: "index_songs_on_composer_id" 23 t.index ["lyricist_id"], name: "index_songs_on_lyricist_id" 24 end 25 26 add_foreign_key "songs", "artists", column: "arranger_id" 27 add_foreign_key "songs", "artists", column: "composer_id" 28 add_foreign_key "songs", "artists", column: "lyricist_id" 29end

試したこと

テーブルを作成後、マイグレーションでsongに外部キーとしてartistを指定するようにマイグレートしました。

Googleで検索したり、公式ドキュメントを見てみたのですが、多対多で同じテーブルを指定するものがなかなか出てきませんでした。

has_manybelongs_toを使うとは思うのですが、いまいちコーディングの仕方が分かりません。

補足情報(FW/ツールのバージョンなど)

外部キーの指定の仕方がそもそもおかしいなどがありましたら、ご指摘のほどよろしくお願いします。

wsl

1rails: rake, version 13.0.6 2ruby: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux] 3node: v14.17.1 4yarn: 1.22.11 5psql: psql (PostgreSQL) 13.4 (Ubuntu 13.4-1.pgdg20.04+1)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

artistは0個以上のsongを持ちます。

songのcomposer_id、lyricist_idは1人以上、arranger_idは0人以上のartistを持ちます。

「0個か1個」ではなく複数になりうるものなのでしたら、中間テーブルを作ることが一般的な手段となります。

投稿2021/09/27 23:03

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yosse95ai

2021/09/27 23:18

なるほど、中間テーブルですか。 中間テーブルを使う場合に、同一のテーブル(今回だとArtist)を参照する場合、 モデルの記述の仕方が分かりません。 参考になる実装事例や記事などありましたら教えて頂きたいです。
maisumakun

2021/09/27 23:36

> 中間テーブルを使う場合に、同一のテーブル(今回だとArtist)を参照する場合、 モデルの記述の仕方が分かりません。 composer、lyricist、arrangerそれぞれ用に別々の中間テーブルを立てるのが、わかりやすさとしてはいいかなと思います。
yosse95ai

2021/09/28 01:25 編集

今朝、たまたま、こういう記事を見つけたのですが、 https://qiita.com/takenobou/items/27ddaef439e2777d875c 中間テーブルを使わない、こういう設計はアンチパターンだったりしませんか? アンチパターンとかでなければ採用してみようと思うのですが、 ご意見いただければとおもいます。 ちなみに、この記事は多対1、なのでしょうか?
maisumakun

2021/09/28 01:26

> 中間テーブルを使わない、こういう設計はアンチパターンだったりしませんか? アンチパターン云々以前の問題として、多対多の場合はこの手法は適用できません。
yosse95ai

2021/09/28 01:58

なるほど。 詳しくありがとうございます。 やはり、中間テーブルを、同一テーブル参照分だけ用意するのがスマートなのでしょうか? > composer、lyricist、arrangerそれぞれ用に別々の中間テーブルを立てるのが、わかりやすさとしてはいいかなと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問