【Rails】アソシエーションについて
本日はアソシエーションについて説明します。
【注意】こちらの記事はコードの細かい説明ではなく、全体イメージをつかむことを重視しているので、そこはご了承ください。
さて、アソシエーションとはモデル(テーブル)間の関係性のことで、has_manyとかbelongs_toとかのあれです。
私が初めてアソシエーションを勉強した時に言葉で解説されてよくわからなかったので、ER図だけではなく、テーブルに具体例を入れて解説したいと思います。
それでは早速解説します。
簡易ブログの例
まず以下のような簡易なブログを想像して下さい。
- ログインするとユーザはメッセージを残せる。
- 誰かが残したメッセージにコメントできる。
イメージは以下の通り
メッセージが3つ投稿されていて、それぞれコメントがあるものとないものがあります。
これをテーブルで表現すると以下のようになります。
少し解説します。
userテーブルはログインできるユーザを定義していて、これらのユーザがメッセージを残したり、コメントのしたりできます。
messageテーブルはメッセージ内容とどのユーザのメッセージかわかるようにuser_idを持ちます。例えばuser_idが2なのはmahomahoさんです。
commentsテーブルはコメント内容とどのユーザのコメントかわかるようにuser_idを持つところまではmessagesテーブルと同じですが、さらにどのメッセージへのコメントかわかるように、message_idを持ちます。
テーブル間の関係性
次にテーブル間の関係性について説明します。
usersテーブルに着目すると1人のユーザは複数のメッセージを残すことができます。例で言えば、mahomahoさんは「釣りスピほしいな」と「LOLほしいな」の2つのメッセージをつぶやいています。
この1つデータが複数のデータを持っている関係性を「1対多」といいます。
ユーザ1に対して、メッセージ多ということです。
モデルでいうと user 「has_many」 messagesに当たります。
逆にメッセージから見ると1つのメッセージは必ずユーザに対応します。ユーザのいないメッセージはありません。
この関係性はモデルでいうと、message 「belongs_to」 userに当たります。
そのほかのテーブル間の関係性も含めてイメージにすると以下のようになります。
1対多「has_many」
- ユーザ1人に対して複数のメッセージ
- ユーザ1人に対して複数コメント
- メッセージ1つに対して複数のコメント
多対1「belongs_to」
- メッセージは必ずユーザを持つ
- コメントは必ずユーザを持つ
- コメントは必ずメッセージを持つ
アソシエーションがあると何が便利か
とその前に、少しモデルとテーブルの話をさせて下さい。
モデルとはテーブルにデータを保存したり、取り出したりする役割を持ったもので、1テーブル1モデルです。
例えばusersテーブルだとUserモデルがそれに当たります(頭文字が大文字なのがポイント)
通常テーブルからデータを取り出そうとすると
「select カラム名 from テーブル名 where 条件」
のようなSQL文が必要になるのですが、モデルがあれば
モデル名.where(条件)
のような簡易な記述でデータが取り出せます。モデル便利!
さて、話をアソシエーションも戻します。
アソシエーションは「モデル間の関係性(≒テーブル間の関係性)」を定義しています。この定義のおかげでデータの取り出しがとても簡単になります。
例をあげます。
あるメッセージに対応するコメントとコメントしたユーザ名を表示したいとき、モデルを使って以下のように記述します。
- コメント → comment.content
- ユーザ名 → comment.user.name
「comment.user.name」がポイントです。
コメントは必ず1人のユーザを持つので、そのユーザの名前をこのようなシンプルな記述で取り出すことができます。
また例えば、あるユーザの全てのメッセージを取り出したい場合にはUserモデルを使って「user.messages」とすることで、複数のメッセージを取り出すこともできます。
このようにアソシエーションを定義することでモデルを使って、関連するテーブルのデータを簡単に取得できるという話でした。
最後にアソシエーションとMVCの関連性を図にしておきます。
MVCの関係性については以下の記事でも解説しているので良ければ、参考にしてください。