LoginSignup
20
22

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-06-27

概要

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

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

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

参考

(1)感動の分かりやすさ。ER図の基礎の基礎知識もあり。初心者必見 :sunrise:
【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】

(2) 理解に苦しんだ・・ 中間テーブルってやつです。
【初心者・独学者向け】Ruby on Railsで中間テーブルを作成し、多対多を実現する

親と子の関係

【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】 がとても分かりやすかったので引用します:pushpin:

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

qiita5.png

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

qiita6.png

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

qiita6.5.png

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

qiita7.png

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

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

qiita7.5.png

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

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

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

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

多対多の関係とは ?

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

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

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

【初心者・独学者向け】Ruby on Railsで中間テーブルを作成し、多対多を実現する

中間テーブルとは?

多対多の関係は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】

20
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
22