9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby on Railsで多対多のテーブル設計を動かしながら理解してみる

Last updated at Posted at 2019-09-13

記事の内容

  • 多対多のアソシエーションとは
  • 中間テーブルとは
  • Railsで多対多のアソシエーションを実装
  • 実際にコンソールで確認してみる

間違っている箇所などありましたらご指摘ください。

多対多のアソシエーションとは

多対多のアソシエーションとは、ある2つのテーブルの関係性が「複数 対 複数」であるということです。
例えば、Qiitaにも実装されている、ブログ記事にタグ付けする機能を実装したいという想定で、1つのブログ記事には複数のタグを関連付けることができる。そして、1つのタグを複数のブログ記事に関連付けることができるという機能を実装します。

  • ブログ記事
    • 複数のタグを設定できる
  • タグ
    • 複数のブログ記事に設定できる

中間テーブルを作成して2つのテーブルを関連付ける

多対多のアソシエーションを実装するために、今回は中間テーブルを使った方法の解説です。
「個人的に中間テーブルと言われてもピンとこない…」という感じだったので画像を交えてみます。

articlesテーブルとtagsテーブルを繋ぐ中間テーブルでそれぞれのidを管理することで多対多のアソシエーションを実装します。

もしarticlesテーブルのレコードが削除された時、関連付いている中間テーブルのレコードも削除されてほしい

Railsで多対多のアソシエーションを実装

それぞれのモデルを生成します。

$ rails g model Article title:string body:string

$ rails g model Tag name:string

$ rails g model ArticleTagRelation article:references tag:references

:referencesと指定することでそれぞれのモデルと関連付けされた状態で生成されます。

app/models/article.rb
class Article < ApplicationRecord
  has_many :article_tag_relations, dependent: :destroy
  has_many :tags, through: :article_tag_relations
end
app/models/tag.rb
class Tag < ApplicationRecord
  has_many :article_tag_relations, dependent: :destroy
  has_many :articles, through: :article_tag_relations
end
  • 中間テーブル
app/models/article_tag_relation.rb
class ArticleTagRelation < ApplicationRecord
  belongs_to :article
  belongs_to :tag
end

has_manyで関連付けする場合は、モデル名は複数形で指定して、belongs_toで関連付けする場合は、モデル名を単数形で指定します。

:dependentはarticleやtagレコードが削除された場合の動作を指定します。
:destroyを指定することで関連付けされた中間テーブルのレコードが削除されます。

:destroyで削除した場合、削除するレコード数分SQLが実行される

Rails consoleで実際に確認してみる

手順

  • rails newして実装を確認
  • 上のモデル生成コマンドで3つのモデルを生成
  • rails consoleでデータを作成
  • 関連付けができているかの確認
  • 削除した時、関連レコードも削除できているか確認
  • DBのテーブルの確認はDB Browser for SQLiteを使う

DB Browser for SQLiteの使用方法

テスト用アプリケーション作成

$ rails new test_app

モデル作成

$ rails g model Article title:string body:string
$ rails g model Tag name:string
$ rails g model ArticleTagRelation article:references tag:references

※rails db:migrateを実行

モデルファイルに関連付け

article.rb
class Article < ApplicationRecord
  has_many :article_tag_relations, dependent: :destroy
  has_many :tags, through: :article_tag_relations
end
tag.rb
class Tag < ApplicationRecord
  has_many :article_tag_relations, dependent: :destroy
  has_many :articles, through: :article_tag_relations
end
article_tag_relation.rb
class ArticleTagRelation < Application
  belongs_to :article
  belongs_to :tag
end

Railsコンソールでデータを作成

$ rails c
> Tag.create(name: 'Rails')
> Article.create(title: 'タイトル', body: 'テスト', tag_ids: [1])

DB Browser for SQLiteでarticle_tag_relationテーブルを確認

Articleモデルのレコードを削除してarticle_tag_relation.rbのレコードも一緒に削除されているか確認

> Article.first.destroy

削除されていれば多対多の関連付けが完了しています。

参考

9
12
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
9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?