2
1

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.

【Rails 6】Active Recordの関連付け機能(アソシエーション)について解説

Posted at

1 対 多の関係モデルの作成

コマンド

rails g model comment board:references name:string comment:text

comment => 1 対 に該当する作成するモデル名
board:references => 1 対 多に該当するモデル名
(:referencesと記述することでboardモデルに紐付けるboard_idがcommentモデルに作成される。)
name:string comment:text => 新しく作成するカラム名とデータ型

作成されたmigrateファイル


class CreateComments < ActiveRecord::Migration[6.0]
  def change
    create_table :comments do |t|
      t.references :board, null: false, foreign_key: true
      t.string :name, null: false
      t.text :comment,null: false

      t.timestamps
    end
  end
end

foreign_key: true は外部キー制約を意味する。
boardsテーブルに存在しないidに対し新規でcommentテーブルのboard_idカラムを作成できない。
即ち、boardテーブルに紐付けられないものは作成できなくするためのもの。

その他
null: falseは入力必須にするためのもの。

テーブルの作成
rails db:migrate

board modelへアソシエーションを記述

board.rb
class Board < ApplicationRecord
has_many: comments
validates :name, presence: true, length: { maximum: 10 }
validates :title, presence: true, length: { maximum: 30 }
validates :body, presence: true, length: { maximum: 1000 }
end

has_many: comments
Boardsテーブルからcommentsテーブルを見たときに, 1 対 多の関係になるため,

Boardモデルに記述するアソシエーションはhas_many: commentsとなる。

comment modelへアソシエーションを記述

comment.rb
class Comment < ApplicationRecord
  belongs_to :board
end

belongs_to :board はモデル作成時に自動で記述される。
belongs_to :boardはcommentモデルから見たboardモデル。

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

中間テーブルboard_tag_relationsを用意して多 対 多のアソシエーションを実現する。

元テーブル 中間テーブル 元テーブル
テーブル名 Boards board_tag_relations Tags
カラム id id id
name board_id name
title tag_id
body

Step1:Tagモデルを作成する

コマンド
rails g model tag name:string

Step2:board_tag_relationsモデル(中間テーブル)を作成する

コマンド
rails g model board_tag_relations board:references tag:references

関連付けれる両方の元テーブルに対してreferences(参照)をつけて関連付けをする。

Step3:モデルの関連付けの追記

作成されたモデルを修正する。

中間テーブルはすでに関連付けをされているのでこのまま。

board_tag_relations.rb
class BoardTagRelation < ApplicationRecord
  belongs_to :board
  belongs_to :tag
end

tagモデル
tagモデルから見た中間テーブルはの関係になるので,has_manyで関連付け。
また関連先のboardsテーブルも指定し,through:(スルー)ここポイント を指定した後に中間テーブルを指定する。

tag.rb
class Tag < ApplicationRecord
    has_many :board_tag_relations
    has_many :boards, through: :board_tag_relations
end

boardモデル

boardモデルから見た、中間テーブルはの関係になるので,has_manyで関連付け。
また関連先のtagsテーブルも指定し,through:(スルー)ここポイント を指定した後に中間テーブルを指定する。

board.rb
class Board < ApplicationRecord
has_many :comments
has_many :board_tag_relations
has_many :tags, through: :board_tag_relations


validates :name, presence: true, length: { maximum: 10 }
validates :title, presence: true, length: { maximum: 30 }
validates :body, presence: true, length: { maximum: 1000 }
end

dependentオプション

dependentオプションとは、モデルに関連されたデータが削除されたときに、その関連に紐付かれたデータも同時に削除する機能

コード

Boardモデル

board.rb
class Board < ApplicationRecord
# 多 対 多の関係のアソシエーション
has_many :comments, dependent: :delete_all   #dependent: :delete_allで削除している
has_many :board_tag_relations, dependent: :delete_all #dependent: :delete_allで削除している
has_many :tags, through: :board_tag_relations


validates :name, presence: true, length: { maximum: 10 }
validates :title, presence: true, length: { maximum: 30 }
validates :body, presence: true, length: { maximum: 1000 }
end

tagモデル

tag.rb
class Tag < ApplicationRecord
    has_many :board_tag_relations :dependent: :delete_all #dependent: :delete_allで削除している
    has_many :boards, through: :board_tag_relations
end

注意点

dependentオプションを使用するときは、controllerのdestroyアクションに使用するメソッドはdeleteメッソッドは使用できないため、替わりにdestroyメソッドを使用する。

controller.rb
def destroy
        @board.destroy #dependentオプションをモデルに設定している場合はdeleteメソッドではなく、destroyメソッドを使用する。
        redirect_to boards_path, flash: { notice: "「#{@board.title}」の掲示板を削除しました。"}
    end
2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?