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" )