テーブル同士を関連付ける設定

[テーブル同士を関連付けさせる方法]

既存のそれぞれのテーブルに以下のようにマイグレーションファイルを記述し、データベース上で紐付けをする。 (1つのUserに対して複数のBoard[掲示板]を持つように[1:多]の関係になるように、BoardにUserを示す外部キー[user_id]を与える。)

[db/migrateファイル]

def up
    execute 'DELETE FROM boards;'                
#executeでクエリが実行される。(既存のboardレコードが存在すると紐付くuserが決められず、[user_id]にNOT NULL制約をしていた場合、設定していたNOT NULL制約に引っかかってしまう為、既存のBoardsテーブルを全て削除)
    add_reference :boards, :user, null: false,  foreign_key: true        
#既存のテーブルに外部キーを追加する。(foreign_keyは、外部キー制約)
end

def down
    remove_reference :boards, :user, foreign_key: true 
end

別な書き方で以下のように記述することもできる。(テーブル作成時に外部キーと外部キー制約を付与)

[db/migrate]

def change
    create_table :boards do |t|
      t.string :title,     null:false
      t.text :body,        null:false
      t.references :user, :null: false, :foreign_key: true
      t.timestamps
    end
end

※注意
・外部キー制約を付ける場合は、自動でインデックスが付与される。
・以下のようにreference型を使わない場合は、[foreign_key: true]では外部キー制約にならない。

[db/migrateファイル]

def change
    create_table :boards do |t|
      t.string :title,     null:false
      t.text :body,        null:false
      t.integer :user_id
      t.timestamps
    end
     add_foreign_key :boards, :users    # add_foreign_key :対象のテーブル名, :指定先のテーブル
end

[外部キー制約とは?]

1.存在しない値を外部キーとして登録できない。 2.子テーブルの外部キーに値が登録されている場合、親テーブルのレコードは削除できない。 上記の2の条件を破る方法は、下記のようにモデルに[dependent: :destroy]オプションを指定する。

[app/models]

has_many :boards, dependent: :destroy       #親モデルが削除された際に、子モデルも一緒に削除する

[関連したモデルのインスタンスを取得する設定方法] 以下のように[1:多]の関係にあるモデルに以下のように記述する。

[app/models]

has_many :boards, dependent: :destroy     #関連付けさせる先のモデル名を複数形にする。
[app/models]

belongs_to :user    #関連付けさせる先のモデル名を単数形にする。

※注意
[has_many]や[belongs_to]は、[validates]より上に記載した方が良い。(rubocop規約のため。)

参考記事:

Railsの外部キー制約とreference型について - Qiita