【Rails】モデルの関連付け（アソシエーション）の概要と使い方

Progateでモデル同士の紐付け（変数の代入で）を学んだけれども、アソシエーションの機能でもっと簡単に出来ると聞いたので調べてまとめてみた。

#アソシエーションとは
【アソシエーション　＝　モデル間の関連付け】

更に言うと、2つのActive Recordモデル同士のつながりを指す。
（Railsの自作したモデルはApplicationRecordモデルを継承し、さらにApplicationRecordモデルはActiveRecord::Baseを継承している）

アソシエーションを利用すると、複数のテーブルにまたがるデータの操作をより簡潔に行うことが出来る。

#テーブル（モデル）間の関係性について

テーブル（モデル）間の関係性については以下３通りが存在する

① 1:1
（例）１人のユーザーに対して、プロフィール写真は１枚存在する

②　　1:n (1:多）
（例）１人のユーザーに対して、複数の記事が存在する

③　　n:m　　（多:多）
（例）記事とタグの関係
→・ある記事はRailsだったりRubyだったり・・・複数のタグをもつ。
　・あるタグ（Railsタグとする）は、様々な記事についている。

#今回例として用いるモデル
※本来であればモデルにしなくても良いものも含んでいるが便宜上として考えてほしいです

・Userモデル
・Userimageモデル　→　Userのプロフィール写真について定義するモデル
・Articleモデル
・Tagモデル
・Article_Tagモデル

| users | userimages | articles | tags | article_tags |
|:-:|:-:|:-:|:-:|:-:|
|   id| id  | id  |  id | id  |id
|   name| name  |name   |  name | article_id  |
|   |   |  user_id |   |   tag_id|

※主キーと外部キーに関して
・主キー　：関係データベースにおける行(レコード)を一意に識別するための列(カラム)(usersテーブルやarticlesテーブル等のid)
・外部キー：他のテーブルとの関連づけに使うキー(articleテーブルのuser_id、article_tagsテーブルのarticle_idやtag_id)

#関連付けの種類
Railsには下記６種類の関連付けが存在するが、今回は①〜④について詳細にみていく
①belongs_to
②has_one
③has_many
④has_many :through
⑤has_one :through
⑥has_and_belongs_to_many

#①belongs_to
【参照元テーブルから参照先テーブルの情報にアクセスする】 (1:1の関係性）
例としてUserモデルとUserimageモデルを使う

```rb:userimage.rb
 class Userimage < ApplicationRecord
  belongs_to :user
 end
```

上記のように書くと、参照先（Userモデル）の情報をUserimageのインスタンスで利用できるようになる。
`@userimage.user.name`→　ユーザーの名前を参照できる

※belongs_to関連付けで指定するモデル名は必ず「単数形」にしなければならない

#②has_one
【１：１の関係を表すことができるアソシエーション】

関係性のみで言えば「belongs_to」と同じだが、has_oneとの使いわけに関しては下記の通り

>has_one関連付けの場合は、その宣言が行われているモデルのインスタンスが、他方のモデルのインスタンスを「まるごと含んでいる」または「所有している」ことを示します。

つまり、UserとUserimage（プロフィール画像）の関係性で言うと
「UserimageはUserに属する」がしっくりとくるので下記のように使い分けると良い

```rb:user.rb
 class User < ApplicationRecord
   has_one :userimage
 end
```

```rb:userimage.rb
  class Userimage < ApplicationRecord
   belongs_to :user
  end
```

`@user.userimage.name`→　プロフィール画像のファイル名を参照できる

#③has_many
【１：nの関係を表すことができるアソシエーション】
・has_many関連付けが使用されている場合、「反対側」のモデルではbelongs_toが使用されることが多い。
・従属する側（今回はarticleモデル)のテーブルに、相手のモデル(今回はuserモデル）のidが必要→テーブルにも紐付けをする

「１人のユーザー（Userモデル）に対して、複数の記事（Articleモデル）が存在する」と言う例の場合

```rb:user.rb
 class User < ApplicationRecord
  has_many :articles # => userはarticleを複数持っていると解釈する
 end
```
※has_many関連付けを宣言する場合、相手のモデル名は「複数形」にする必要がある。

```rb:article.rb
 class Article < ApplicationRecord
  belongs_to :user # => articleはuserに従属すると解釈する
 end
``` 

上記２点を書けば・・・記事名を表示できる

```rb:コントローラ側
@user = User.find_by(id:1)
```

```rb:ビュー側
<% @user.articles.each do |article| %>
  <%= article.name %>
<% end %>
```

※belongs_toと違い、articlesメソッドの戻り値が配列になることに注意

#④has_many :through
【m:nの関係を表すアソシエーション】
前半で例としたように、「記事とタグの関係」を例としてみていく
今回登場するモデルは下記の通り

|articles | article_tags | tags |
|:-:|:-:|:-:|
| id |id| id  |
|name   | article_id |  name |
|  user_id(今回関係なし）|   tag_id|   |


```rb:article.rb
 class Article < ApplicationRecord
  has_many :article_tags
  has_many :tags, through: :article_tags
 end
```

```rb:tag.rb
 class Tag < ApplicationRecord
  has_many :article_tags
  has_many :articles, through: :article_tags
 end
```
```rb:article_tag.rb
 class ArticleTag < ApplicationRecord
  belongs_to :article
  belongs_to :tag 
 end
```

タグ名を取り出したい場合は・・・

```rb:コントローラ側
@article = Article.find(1) # id:1の記事情報
```

```rb:ビュー側
#情報を取り出す際は繰り返し処理！
<% @article.tags.each do |tag| %>
  <li><%= tag.name %></li>
<% end %>
```

※ちなみにArticle_tagテーブルに値をrails consoleで入れる際は
`ArticleTag.new(article_id: "1", tag_id: "1")`
とモデル名の通り入れる（Article_tag.newだといつまでたっても値入れられない！←ハマりました・・・）

このようにアソシエーションを使うことで、一つ一つのモデルを順を追って操作していたものが、簡単・簡潔になる。


#参照
Ruby on Railsガイド　：　https://railsguides.jp/association_basics.html
【Rails初心者向け】モデル間の関連付け（アソシエーション）まとめ：　https://qiita.com/To_BB/items/47d2c7b1bc3513025d7b
Rails モデルの関連付け(アソシエーション)：https://qiita.com/taigamikami/items/d6a2b5e4611eb4d8e13a