Rails 多対多のモデルを作る

Railsで多対多のモデルを作るには、has_many :through関連づけを使います。

ここでは先生モデル(Teacher)生徒モデル(Student)を第3のモデルの授業モデル(Lesson)を介して多対多で関連づけてみます。

Step1. モデルの作成

rails generate model 単数形でモデルを作ります。

$ rails generate model teacher
$ rails generate model student
$ rails generate model lesson

Teacherモデルはhas_many :結合モデルの複数形で結合モデルを指定し、has_many :接続先の複数形, through: :結合モデルの複数形Studentモデルに接続します。

class Teacher < ApplicationRecord
 has_many :lessons
 has_many :students, through: :lessons
end

Studentモデルも同様にTeacherモデルに接続します。

class Student < ApplicationRecord
 has_many :lessons
 has_many :teachers, through: :lessons
end

結合モデルのLessonbelongs_to :単数形TeacherモデルとStudentモデルをつなぎます。

class Lesson < ApplicationRecord
 belongs_to :teacher
 belongs_to :student
end

Step2. マイグレーション

上のモデルに対応するマイグレーションは次のようになります。ポイントは結合モデルのLessonです。t.belongs_to :単数形TeacherモデルとStudentモデルのIDを生成しています。

def change
 create_table :teachers do |t|
  t.string :name
  t.timestamps
 end

 create_table :students do |t|
  t.string :name
  t.timestamps
 end

 create_table :lessons do |t|
  t.belongs_to :teacher
  t.belongs_to :student
  t.timestamps
 end
end

Step3. 使い方

has_manyで接続したモデルは、ActiveRecord::Associations::CollectionProxyクラスとなります。

下記のteacher_objTeacherモデルのインスタンス。student_objStudentモデルのインスタンスです。

一覧を表示する。

teacher_obj.students

追加しようとしているオブジェクトが含まれるか確認する。含まれていればtrueが返る。

teacher_obj.students.include?(students_obj)
=> true

追加する。

teacher_obj.students << student_obj

追加できたか確認するときは、(true)を指定してキャッシュを破棄して表示する。

teacher_obj.students(true)

1件削除する。

teacher_obj.students.delete( student_obj )

すべて削除する。

teacher_obj.students.clear

個数を返す。

teacher_obj.students.size

検索する。

teacher_obj.students.where( name: "Taro" )