【Rails】アソシエーションとは?概要とその種類を紹介

ここではRailsの「アソシエーション」についてまとめたいと思います。これまでn回書かれてきた話題ですが、ここでは私なりに勉強して学んだこととしてアウトプットしたいと思います。

Contents

アソシエーションとは

Railsの「関連付け(アソシエーション: association)」は、2つのActive Recordモデル同士のつながりを指します。 (Active Record の関連付け – Railsガイド

言い換えるなら、データベースのテーブル同士の関係(1対1/1対多/多対多など)のRailsでの表現ということですね。

アソシエーションの種類

belongs_to

belongs_toは、そのテーブルが引数に指定した対象テーブルに所属するときに使います。

belongs_to({対象モデル名} [, scope, options])

このbelongs_toを指定すると、指定した側のクラスに対象テーブルに紐つく外部キーが作成され、自テーブル→対象テーブルという1方向の「1対1関係」がつくられます。つまり「自テーブルは対象テーブルを知っている」が、「対象テーブルは自テーブルについて知らない」状態になります。

双方向のアソシエーションは、後述のhas_oneやhas_manyを併用して実現します。

指定できるオプション

  • :class_name 関連するモデルクラス名を指定。関連名と参照先のクラス名を分けたいとき(後述)に利用します
  • :dependent :destroyで参照先レコードが削除される場合に、参照元レコードもDBから削除
  • :foreign_key 参照先のテーブルの外部キーのカラム名
  • :primary_key 参照元(自テーブル)の外部キーのカラム名
  • :optional trueを指定すると参照先テーブルに該当データがない場合もエラーにならない
  • :required trueを指定すると関連づけの確認がなされる。

オプションについてより詳しくは、こちらに記載があります。

「関連名と参照先のクラス名を分ける」?

以下のように書いたときの:admin_userが「関連名」、Userが「参照先のクラス名」です。

belongs_to :admin_user, class_name: 'User'

has_one

has_oneは自テーブルが対象テーブルを1つ持っている場合に使います。どういうことでしょう。belongs_toとの比較でいうと、「has_oneは対象テーブルが自テーブルに対する外部キーを持つ」という場合に利用します。一方で先述の通り、belongs_toは「自テーブルが対象テーブルに対する外部キー」を持ちます。つまり先ほども書いたように、belongs_toとhas_oneとを併用することで双方向の関連づけを定義でき、この場合は双方向「1対1」関係となります。

has_one(関連モデル名 [, scope ,オプション])

has_many

has_manyはその名の通り、対象モデルとの「1対多」関係をなします。例えば以下のように実装した時、:authorが「1」、:booksが「多」です。

class Author < ApplicationRecord  has_many :booksend---class Book < ApplicationRecordbelongs_to :authorend

has_many :through

has_many :thoughは、他方のモデルと「多対多」関係を設定する際に利用されます。RDBでは自テーブルと対象テーブルとを「多対多」関係で結ぶ時、それぞれが中間テーブルと「1対多」関係をなすことで実現しますが、railsではその中間テーブルを:throughで指定することで実装します。

例えば以下は、userとsessionとをsession_participantを中間テーブルにして「多対多」にしています。

class User < ApplicationRecordhas_many :session_participantshas_many :sessions, through: :session_participantsend---class Session < ApplicationRecordhas_many :session_participantshas_many :users, though: :session_participantsend---class SessionParticipant < ApplicationRecordhas_many :usershas_many :sessionsend

ちなみに「多対多」はhas_and_belongs_to_manyを用いても以下のように実現できます。

class User < ApplicationRecordhas_and_belongs_to_many :sessionsend---class Session < ApplicationRecordhas_and_belongs_to_many :usersend

参考

belongs_to/has_one/has_manyの簡単まとめ

テーブルの関連付け(一対一、一対多、多対多) – subaru-hello’s blog

Active Record の関連付け – Railsガイド

Rails5からbelongs_toアソシエーションの挙動が変わった – SHOYAN BLOG

ActiveRecord::Associations::ClassMethods

やさしい図解で学ぶ 中間テーブル 多対多 概念編 – Qiita

has_and_belongs_to_manyメソッドを使用してモデルを関連付けする – Qiita

最新情報をチェックしよう!