迷い人

日々勉強。勉強の先に何か見つかるといいなぁ

【Rails】アソシエーションについて

本日はアソシエーションについて説明します。

 

 

【注意】こちらの記事はコードの細かい説明ではなく、全体イメージをつかむことを重視しているので、そこはご了承ください。

 

 

さて、アソシエーションとはモデル(テーブル)間の関係性のことで、has_manyとかbelongs_toとかのあれです。

 

私が初めてアソシエーションを勉強した時に言葉で解説されてよくわからなかったので、ER図だけではなく、テーブルに具体例を入れて解説したいと思います。

 

それでは早速解説します。

 

簡易ブログの例

まず以下のような簡易なブログを想像して下さい。

 

  • ログインするとユーザはメッセージを残せる。
  • 誰かが残したメッセージにコメントできる。

 

イメージは以下の通り

 

f:id:oyaoya1123:20191106020541p:plain

 

メッセージが3つ投稿されていて、それぞれコメントがあるものとないものがあります。

 

これをテーブルで表現すると以下のようになります。

 

f:id:oyaoya1123:20191106020804p:plain

 

少し解説します。

 

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に当たります。

 

そのほかのテーブル間の関係性も含めてイメージにすると以下のようになります。

 

f:id:oyaoya1123:20191106023007p:plain

 

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の関連性を図にしておきます。

 

f:id:oyaoya1123:20191106030844p:plain

 

 

MVCの関係性については以下の記事でも解説しているので良ければ、参考にしてください。

 

【Rails】MVCについて - 迷い人