PR

Railsのbelongs_toを使った関連付けの方法を解説

Ruby・Rails

Railsには、belongs_toというアソシエーションが用意されています。本記事では、Railsを利用する際に、アソシエーションとはどのように機能するのか、その中で、belongs_toはどのような場合に使えるのかについて解説します。

Railsのアソシエーションとは

Ruby on Rails(以下、Railsと記述します)では、2つのActive Recordモデル同士のつながり(関連付け)をアソシエーションと呼んでいます。各モデル間には関連付けを宣言する必要があります。

モデル間の関連付けを宣言することで、1つのコードから関連情報をたどることができます。Active Recordの関連付けを行うと、2つのモデルの間のつながりを明示的にRailsに対して宣言できます。

belongs_toとは

モデルに対し、belongs_toで関連付けを行なうと、相手となるモデルとの間に「1対1」のつながりが設定されます。belongs_toで関連付けを宣言したモデルの、すべてのインスタンスは、相手となるモデルのインスタンスに従属します。

Railsアプリケーションで著者(Author)と書籍(Book)の情報を扱う場合、必ず1人の著者につき1冊しか書籍情報がなければ、belongs_toで宣言します。

belongs_toを使って関連付けを行う方法

belongs_toは、自分のテーブルと相手となるテーブルの関係が1対1で、従属関係にある場合のモデルの関連付けに使います。

1対1で従属関係にあるとは、相手モデルのテーブルに外部キーとして、自分モデルのidカラムを参照している関係にある2つのテーブルを指します。

belongs_toの書き方

Railsのbelongs_toを使って、2つのモデルの関連付けを宣言する場合、以下の形式に従って、コードを記述します。

【記述形式】
belongs_to(関連モデル名 [, scope, オプション])

指定する関連モデル名は、相手モデルの名前の単数形になります。以下によく使われいるオプションを紹介するので、参考にしてみてください。。

オプション内容
:class_name関連するモデルクラス名を指定する
関連モデル名と参照先のクラス名を分けたい場合に使う
:foreign_key参照先のテーブルの外部キーのカラム名を指定する
:primary_key参照元(自分)のテーブルの主キーのカラム名を指定する
:optional「true」を指定すると参照先のテーブルのデータが存在しない場合でもエラーにならない

関連名をカスタマイズする方法

Railsのbelongs_toは、カスタマイズせずに基本の構文のまま使用できますが、関連付けの動作をカスタマイズする必要のある場合もあります。Railsのbelongs_toのカスタマイズを行う際は、作成するときに渡すオプションとスコープブロックを使います。

belongs_to関連付けでは、先にご紹介したよく使われるオプションのほか、以下のオプションがサポートされています。

オプション内容
:autosave「true」に設定すると、親オブジェクトが保存されるたびに、読み込まれているすべての関連付けメンバを保存し、destroyフラグが立っているメンバを破棄する
:counter_cache従属しているオブジェクトの数の検索効率を向上させる
:dependentオブジェクトが削除されるときに、関連付けられたオブジェクトが直接データべースから削除される
:inverse_of関連付けの逆関連付けとなるhas_many関連付けまたはhas_one関連付けの名前を指定する
:polymorphicポリモーフィック関連付けを指定できる
:touch関連付けられているオブジェクトが保存またはdestroyされるたびに、そのオブジェクトのupdated_atまたはupdated_onタイムスタンプが現在時刻に設定される
:validate「true」に設定すると、関連付けられたオブジェクトが保存時に必ず検証される

関連付けで指定するモデル名は必ず単数形にする

Railsのbelongs_toで宣言するモデルの関連付けは、1対1です。そのため、belongs_toで指定する相手モデル名は、必ず単数形で指定します。1対多の関連付けとなるhas_manyアソシエーションでは、相手モデル名は必ず複数形で指定します。

Railsのbelongs_to以外のアソシエーション

RailsのActive Recordでテーブル間の関連付け(アソシエーション)を行うメソッドには、belongs_toのほか、has_one、has_manyもあります。これらの違いと使い方について、簡単に説明します。

こんな場合使えるアソシエーション
自分のモデルが相手となるモデルに従属しているbelongs_to
自分のモデルと相手となるモデルが1対1has_one
自分のモデルと相手となるモデルが1対多has_many

has_oneに寄る関連付け

Railsのhas_oneは、相手となるモデルとの間に1対1の関連付けを設定します。belongs_toと似ていますが、has_oneの場合は、その宣言が行われているモデルのインスタンスが、他方のモデルのインスタンスを「まるごと含んでいる」という点で異なります。

【記述形式】
has_one(関連モデル名 [, scope ,オプション])

オプションとしては、主に以下のものがよく使われています。

オプション内容
:class_name関連するモデルクラス名を指定する
関連モデル名と参照先のクラス名を分けたい場合に使う
:foreign_key参照先のテーブルの外部キーのカラム名を指定する
:primary_key参照元(自分)のテーブルの主キーのカラム名を指定する

has_manyによる関連付け

Railsのhas_many関連付け、他のテーブルとの間に「1対多」のつながりがあることを示します。
参照相手となるモデルでは、多くの場合belongs_toが使われます。has_manyで関連付けを宣言する場合、相手となるモデル名は「複数形」にする必要があります。

【記述形式】
has_many(関連モデル名 [, scope ,オプション])

オプションとしては、以下のものがよく使われています。

オプション内容
:class_name関連するモデルクラス名を指定する
関連モデル名と参照先のクラス名を分けたい場合に使う
:foreign_key参照先のテーブルの外部キーのカラム名を指定する
:primary_key参照元(自分)のテーブルの主キーのカラム名を指定する

has_many :throughによる関連付け

has_many :throughは、相手となるモデルと「多対多」のつながりを設定する場合に使われます。

A、B、Cのモデルがあり、AとBを直接関連付けることはできないものの、間にCを介すことで、AからCをたどり、CからBをたどって、結果的にAとBが紐づく場合に、has_many :throughで関連付けを宣言することができます。

各アソシエーションの記述例

Railsの各アソシエーションの記述形式の「関連モデル名」部分は、モデル間のが「1対1」か「1対多」かによって、モデル名を単数形・複数形いずれで記述するかの使い分けが必要です。

【記述例】authorモデルとの関連付けを宣言する場合
belongs_to :author
has_one :author
has_many :authors
has_many :publishers, through: :authors

Railsのアソシエーションを覚えておこう!

モデルの関連付けは、一種のマクロ的な呼び出しとして実装されます。アソシエーションによって、モデル間の関連付けを宣言的に追加することができます。

belongs_toによって、あるモデルが他のモデルに「従属している」と宣言すると、2つのモデルのインスタンス間で、「主キー」と「 外部キー」の参照情報を保持するように、Railsに指示が伝わります。ほかのアソシエーションもまとめて使い方を覚えておきましょう。

タイトルとURLをコピーしました