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
結合モデルのLessonはbelongs_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_objはTeacherモデルのインスタンス。student_objはStudentモデルのインスタンスです。
一覧を表示する。
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" )