概要
前回のモデルの関連付けの種類の記事の続きです。
モデルの関連付けの際に使用できるオプションについてアウトプットしていきたいと思います。
前回の記事
環境
ruby: '3.0.1'
rails: '6.1.4'
前提
今回説明するにあたって下記のモデルを想定しています。
usersテーブル
id | name |
---|---|
1 | user1 |
2 | user2 |
departmentsテーブル(所属部署を管理するテーブル)
id | name |
---|---|
1 | 営業部 |
2 | 開発部 |
Assignmentsテーブル(所属部署を管理するテーブル)
id | user_id | department_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 1 |
オプションの種類
1. through
through
は__多対多__の関係のモデル同士を関連付ける際に、そのモデル同士の中間に設置するモデルを経由させる際に使用します。
使い方
models/user.rb
class User < ApplicationRecord
has_many :assignments # まずは中間のモデルとの関連付け
has_many :departments, through: :assignments # 多対多のモデルを関連付ける際にthroughオプションに中間のモデルを記載
end
models/assignment.rb
class Assignment < ApplicationRecord
belongs_to :user # userと従属の関係
belongs_to :department # departmentと従属の関係
end
models/department.rb
class Department < ApplicationRecord
has_many :assignments
has_many :users, through: :assignments
end
関連付けを行うことで下記のように直接departmentsやusersにアクセスできます。
user = User.find(1)
user.departments #=> user1が所属する部署一覧を取得
department = Department.find(1)
department.users #=> その部署に所属しているユーザーを取得
<備考> 中間テーブルの必要性
中間テーブルがなぜ必要かを説明します。
結論から言うと、テーブル設計の冗長性をなくすためです。
たとえば、一人のユーザーが営業部と開発部の両方に所属、また営業部には複数のユーザーが所属していると仮定します。
このような場合、テーブルを管理する際に下記のように所属部署が増えるたびにカラムが増えることになります。
usersテーブル
id | name | department_id_1 | department_id_2 | ・・・ |
---|---|---|---|---|
1 | user1 | 1 | 2 | ・・・ |
departmentsテーブルも同様に所属ユーザーが増えればカラムが増えてしまいます。
これを解決するために中間テーブルを設置します。
Assignmentsテーブル(所属部署を管理するテーブル)
id | user_id | department_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 1 |
ユーザーの所属部署を中間テーブル(Assignmentsテーブル)で管理することで
usersテーブルやdepartmentsテーブルでは先程のような冗長性はなくなります。
2. foreign_key
foreign_key
は外部キーを変更したい場合に使用するオプションです。
通常関連付けを行うと外部キーは__'関連付けモデル名'+_id__になります。
これを別の名称に変更することができます。
使い方
models/user.rb
class User < ApplicationRecord
has_many :assignments, foreign_key: 'user_number'
end
上記のように記載することで参照元の外部キーをuser_id
からuser_nubmer
変更することができます。
フォロー、フォロワー機能の実装のように同じテーブル同士を中間テーブルを介して関連付けを行う際に使用したりします。
3. class_name
class_name
は関連付けを行う関連名を変更する際に使用するオプションです。
関連名を変更してしまうと、どのモデルと関連付けされているのか判断できなくなるため
関連付け先のモデル名を記載します。
使い方
models/department.rb (他のモデルの設定は)
class Department < Application
has_many :assignments
has_many :employees, through: :assignments, class_name: 'User' # class_name追加
end
models/user.rb
class User < ApplicationRecord
has_many :assignments
has_many :departments, through :assignments
end
models/assignment.rb
class Assignment < ApplicationRecord
belongs_to :user
belongs_to :department
end
これにより下記のように参照の仕方を変えることができます。
department = Department.find(1)
# class_name追加前
# department.users
# class_name追加後
department.employees # 部署に所属してるユーザーが取得できる
4. dependent
dependent
はテーブルのデータが削除された際に関連付けられているデータも削除するときに使用します。
使い方
models/user.rb
class User < ApplicationRecord
has_many :assignments, dependent: :destroy
end
上記のように設定するとユーザーが削除された際に紐付いているassignmentsテーブルのデータも削除されるようになります。
まとめ
以上がよく使われるオプションになります。
他にもオプションはたくさんありますので詳しく確認したい場合は下記参考文献を参照ください。
参考文献