記事の内容
- 多対多のアソシエーションとは
- 中間テーブルとは
- 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
と指定することでそれぞれのモデルと関連付けされた状態で生成されます。
class Article < ApplicationRecord
has_many :article_tag_relations, dependent: :destroy
has_many :tags, through: :article_tag_relations
end
class Tag < ApplicationRecord
has_many :article_tag_relations, dependent: :destroy
has_many :articles, through: :article_tag_relations
end
- 中間テーブル
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を使う
テスト用アプリケーション作成
$ 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を実行
モデルファイルに関連付け
class Article < ApplicationRecord
has_many :article_tag_relations, dependent: :destroy
has_many :tags, through: :article_tag_relations
end
class Tag < ApplicationRecord
has_many :article_tag_relations, dependent: :destroy
has_many :articles, through: :article_tag_relations
end
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
削除されていれば多対多の関連付けが完了しています。