0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Railsの関連付けのオプションについて

Last updated at Posted at 2022-01-09

概要

前回のモデルの関連付けの種類の記事の続きです。
モデルの関連付けの際に使用できるオプションについてアウトプットしていきたいと思います。
前回の記事

環境

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テーブルのデータも削除されるようになります。

まとめ

以上がよく使われるオプションになります。
他にもオプションはたくさんありますので詳しく確認したい場合は下記参考文献を参照ください。

参考文献

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?