1体多関連の復習
まずは1体多の関連を復習し、それからどのような場合に多対多の関連を付けるべきなのかを見ていきましょう。
関連ですので、二つモデルを用意します。一つはAuthorもう一つはBookにしましょう。
それぞれ著者と書籍を表すクラスです。書籍は一人の著者に書かれており、一人の著者は複数の書籍を出版しているとします。
この時、1体多の関連を作成するには、Bookクラスにauthor_idというカラムを定義し、次のようにクラスを記述するのでした。
class Author < ApplicationRecord
has_many :books
end
class Book < ApplicationRecord
belongs_to :author
end
このように定義することで、次のようなメソッドを使うことができます。
author = Author.find(id)
# ある著者が書いた書籍の配列
# author_idがauthorのidと同じ値であるbookを取得
author.books
book = Book.find(id)
# ある書籍の著者
# bookが持つauthor_idと同じ値をidに持つauthorを取得
book.author
しかし、実際には一つの書籍に複数の著者がいるという状況の方が一般的です。
ですので、book.authors
とauthor.books
の双方向で複数の値を取得できるのが理想的です。現状、bookには一つのauthor_idを持つことしかできないので、何かしらの改修が必要になります。
多対多の実装
そこで多対多の関連が必要となってきます。
多対多の関連にはAuthor,Bookの他に中間クラスと言われるAuthorBookクラスを追加します。
このAuthorBookクラスはauthor_idとbook_idを持っており、著者と書籍の関連1つに付き1レコード生成されます。
ではモデルを作っていきましょう。
rails g model author_book author:references book:references
rake db:migrate
author:references,book:referencesと書くことでそれぞれのクラスと紐付けがされます。
次に各クラスを修正していきます。
class Author < ApplicationRecord
has_many :author_books
has_many :books, through: :author_books
end
class Book < ApplicationRecord
has_many :author_books
has_many :authors, through: :author_books
end
class AuthorBook < ApplicationRecord
belongs_to :book
belongs_to :author
end
これで準備は整いました。では実験してみましょう
book = Book.create
author1 = Author.create
author2 = Author.create
book.authors
この時点ではまだ中間クラスによる関連付けが存在しないので、書籍に関連する著者は表示されないはずです。
AuthorBook.create(author_id: author1.id, book_id: Book.id)
AuthorBook.create(author_id: author2.id, book_id: Book.id)
book.authors
では次はどうでしょうか?
設定がちゃんと出来れいれば2つのauthorインスタンスが表示されているはずです。
簡単ですが多対多の関連付けの説明は以上になります。
多対多の関連は例えば、投稿に対するイイね機能や俳優と出演作品の関連などに用いられます。
複数のモデルが出てきて複雑になってきましたが、使いこなして複雑なデータ構造も扱えるようにしましょう。