ER図 と アソシエーションを100%理解する

##概要 

モデル同士の繋がりを指す**アソシエーション（関連付け）**:paperclips:
定義しておくと***モデルをまたいだデータの呼び出しが可能になります。***




また親と子の関係や、外部キーの設定などを理解していないと、
「親モデルのデータを先に追加しないと子のデータが追加できない。」なんて
DB設計の見直しが起きる可能性も・・:fearful:

データベースを可視化できるER図はとても大切。学習メモとして残します:blossom::sunny:

##参考

（１）感動の分かりやすさ。ER図の基礎の基礎知識もあり。初心者必見 :sunrise:
[【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1#%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E6%A9%9F%E8%83%BD%E3%81%A8%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E6%A9%9F%E8%83%BD%E3%82%92er%E5%9B%B3%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E8%A8%AD%E8%A8%88%E3%81%97%E3%82%88%E3%81%86)

（２） 理解に苦しんだ・・ 中間テーブルってやつです。
[【初心者・独学者向け】Ruby on Railsで中間テーブルを作成し、多対多を実現する
](https://programming-beginner-zeroichi.jp/articles/25)

## 親と子の関係

[【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1#%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E6%A9%9F%E8%83%BD%E3%81%A8%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E6%A9%9F%E8%83%BD%E3%82%92er%E5%9B%B3%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E8%A8%AD%E8%A8%88%E3%81%97%E3%82%88%E3%81%86) がとても分かりやすかったので引用します:pushpin:

>モデル同士の親子関係とは
図で考えてみましょう。
Aさん(User)は、自分が作ったブログサイトでたくさんの記事(Article)を投稿します。

>![qiita5.png](https://camo.qiitausercontent.com/548f6a035148bfe787f9469cc259605f2803da86/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3230383033382f34313032353934632d623037392d393537632d376439302d6238643565333930343263352e706e67)

>Bさんも少しは投稿します。

>![qiita6.png](https://camo.qiitausercontent.com/abcdee4d4357449becf3564c9a7e9fa993b3161f/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3230383033382f33396631366362372d303535322d626161362d633939392d3533663638383432633066372e706e67)

>つまり、User一人一人は沢山のArticleを持っている(User has many articles.)、と考えることができます。(この突然出てきた英文は伏線ですよ！！！！)

>![qiita6.5.png](https://camo.qiitausercontent.com/981ad50137b0cac854f91361dc4319f079343ffa/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3230383033382f39323937616137332d653537382d323937612d336564652d3564353762656565316131662e706e67)

>逆の立場(Article)も考えてみましょう。
ある日投稿された記事(Article)は、Aさん(User)によって書かれました。

>![qiita7.png](https://camo.qiitausercontent.com/7f54b9e0bd85e99af0acfe89e0d7598c24724279/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3230383033382f30663634656435322d316436312d323030612d303938312d3835623061363834633034302e706e67)

>次の日投稿された記事はBさんによって書かれました。
他の日に投稿された記事も、それぞれAさん、Bさんどちらかによって書かれた記事です。Aさん、Bさんが共作で書いた記事というのはありえません。

>つまり、Articleは誰か一人のUserに所属している(Article belongs to a user.)と考えることができます。

>![qiita7.5.png](https://camo.qiitausercontent.com/1ef0e7407c3a08b09fa1e87c0e27e577fbc21198/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3230383033382f65626338633762652d643963372d663362632d323334362d3532633232623034383864332e706e67)

**UserがいなくてはArticleは生まれないし、Articleは必ず誰か一人のUserから生まれます。そう、Userが親でArticleが子となっているわけなのです。これが親子関係です。**

 **このような関係をUserとArticleは一対多の関係または1:Nの関係といいます。
もちろんUserが1でArticleが多です。**

この親と子の関係をつくるためのデータベース上でのモデルの関連付けをアソシエーションといい
アソシエーションしないと、どのユーザーがどの記事が書いたのか分かりません。



## 多対多の関係と中間テーブル

####多対多の関係とは ？

どちらのモデルから見ても、自分も相手も複数×複数になる状態です。

>記事から見るとカテゴリーを複数持っているので、記事に対して、カテゴリーは多になります。
>
>カテゴリーから見ると１カテゴリーに複数の記事が関連しているので、カテゴリーから見ると記事は多になります。 この>関係が多対多になります。

[【初心者・独学者向け】Ruby on Railsで中間テーブルを作成し、多対多を実現する
](https://programming-beginner-zeroichi.jp/articles/25)

####中間テーブルとは？

多対多の関係は2つのモデルでは実現できないんです。
え、なぜ？:disappointed_relieved:

例えば、先ほどの記事とカテゴリーの例。

【記事テーブル】

|  id  |  記事タイトル  |
| ---- | ---- |
| ❶ | |
| ❷ | |

記事ができる度に、自動生成のidが付いていきます。
主キー（primary key）ですね。


【カテゴリーテーブル】

|  id  |  カテゴリー名  |
| ---- | ---- |
| ① | 日常 |
| ② | Rails |


【中間テーブル】

|  id  |  記事タイトル  |  カテゴリー名  |
| ---- | ---- | ---- |
| １ |❶|①|
| ２ |❶|②|
| ２ |❷|②|
| ２ |❷|①|

可能性の話ですが、上記のように 1つの記事がもしかしたら何個もカテゴリーを持つかもしれないわけです。
「記事タイトル」： ライフスタイル / アウトドア / 子育て　とかそんな感じでしょうか。

今はまだ記事タイトルもカテゴリーもどちらも2つしかないので、
中間テーブルいらなくない？ってなると思います。でも記事とカテゴリーはどちらもどんどんどんどん増えていく可能性がある・・ 

そうするとこの組み合わせは無限大になるし、
カラム数は最初に設定したらもう増やせないので、多対多の間は中間テーブルで対応してあげます。



#### モデルの関連性設定に `has_many, through:`が加わります！

上の例で引き続き。
中間テーブルができるとモデルの関連性設定が変わります :fist_tone4:

まずはマイグレーションを実行。

```20190627075545_create_categories_articles.rb
class CreateCategoriesArticles < ActiveRecord::Migration
  def change
    create_table :categories_articles do |t|
      t.integer  :category_id
      t.integer  :article_id
      t.timestamps null: false
    end
  end
end
```

次に中間テーブルで記事モデルとカテゴリーモデルとの関連付けを行う。

```models/categories_ariticles.rb
class CategoriesArticle < ActiveRecord::Base
  belongs_to :category
  belongs_to :article
end
```

記事モデルの関連付け :paperclips:

```models/article.rb
class Article < ActiveRecord::Base

  has_many :categories_articles
  has_many :categories, through: :articles_categories

end
```

カテゴリーモデルの関連付け :paperclips:

```models/category.rb
class Category < ActiveRecord::Base
  has_many :categories_articles
  has_many :articles, through: :categories_articles
end
```

中間テーブルを通して繋がっているものには、
`through::` というkeyをつけます。

throughオプションによりarticles経由でcategoryにアクセスできるようになります:lemon:


## 外部キーとは？ （foreign key）

リレーショナルデータベース(RDB)で、テーブルのある列に、別のテーブルの特定の列に含まれる項目しか入力できないようにする制約。



## 商品が消えたら、いいねも消える

例えば、あるECサイト
ユーザーのマイページには自分がいいねした 「いいね一覧」 があるとします。
個人的には商品がもう存在しない場合には、いいねも消えてしまっていいのでは？と思います。

そんな時は`dependent: :destroy`を使います:fist_tone3:

### dependent: :destroy の役割

商品といいねのモデルには、以下のようなリレーションの記載があります。

```models/product.rb
class Product < ApplicationRecord

has_many :favorites, dependent: :destroy

end
```

```models/favorite.rb
class Favorite < ApplicationRecord
	belongs_to :user
	belongs_to :product
end
```

`dependent: :destroy`と言う箇所は、親にあたる投稿が削除されたら、
子をどう扱うのかオプションを設定できるという感じです。今回は消去するので`:destroy`
残しておいて良いのであれば、何も記載しなくてOkay

[【Rails】ActiveRecordの:dependent使い分けまとめ【: destroy, :delete, :nullify】
](https://www.stacky-health.work/2018/08/17/ruby_on_rails_dependent/)