Railsマイグレーションにおけるreferencesの使い方

Railsのマイグレーションにおけるreferencesの使い方を探していませんか?

ぼくも業務でRailsの中間テーブルを作る際にreferences型を使ったんですが、null: falseは必要なのか、foreign_key: trueは必要なのか、など迷いますよね?

そこでこの記事ではreferencesの使い方や実装例を具体例つきで解説します。

最後まで読めば、referencesを上手に使いこなせるようになります。

この記事を書いているぼくは実務経験1年。独学で未経験から従業員300名以上の自社開発企業へ転職しました。実務ではVue.jsとRailsを毎日書いています。

目次

references型の使い方

referencesのオプションとそれぞれのデフォルト値をまとめます。

オプション説明デフォルト値
:typeカラムのデータ型:bigint
:indexインデックスを付与するかtrue
:foreign_key外部キーの制約false
:polymorphicポリモーフィックの付与false
:nullNULLを許容するか?true

インデックスこそデフォルトで付与してくれますが、外部キー制約はそのままでは付かない、とのことでした。

なので外部キー制約のついたカラムを作りたい場合は、マイグレーションファイル内でforeign_key: trueを書くのが適切です。

中間テーブルの実装例

# UserとPostの中間テーブルとしてBookmarkを作る(foreign_key: trueを使用)
class CreateBookmarks < ActiveRecord::Migration[6.1]
  def change
    create_table :bookmarks, comment: 'ブックマーク' do |t|
      t.references :user, foreign_key: true
      t.references :post,   foreign_key: true

      t.timestamps
    end
  end
end

もしくは次のようにadd_foreign_keyを使って書いてもOKです。

# UserとPostの中間テーブルとしてBookmarkを作る(add_foreign_keyを使用)
class CreateBookmarks < ActiveRecord::Migration[6.1]
  def change
    create_table :bookmarks, comment: 'ブックマーク' do |t|
      t.references :user
      t.references :post

      t.timestamps
    end
    # add_foreign_key :参照先テーブル, :参照元テーブル
    add_foreign_key :bookmarks, user
    add_foreign_key :bookmarks, post
  end
end

referencesを使うとuser_idとpost_idにはインデックスが自動で貼られます。

なので必要に応じて、以下のようにuser_idとpost_idの複合インデックスだけ貼ればOKですね。

# UserとPostの中間テーブルとしてBookmarkを作る
class CreateBookmarks < ActiveRecord::Migration[6.1]
  def change
    create_table :bookmarks, comment: 'ブックマーク' do |t|
      t.references :user, foreign_key: true
      t.references :post,   foreign_key: true

      t.timestamps
    end
   # 
    add_index :bookmarks, [:user_id, :post_id], unique: true
  end
end

referencesを使わない場合

referencesを使わないと中間テーブルが作れないわけではありません。

referencesを使わずに同じテーブルを作ろうとすると、次の記述になります。

# UserとPostの中間テーブルとしてBookmarkを作る(referencesを使わない)
class CreateBookmarks < ActiveRecord::Migration[6.1]
  def change
    create_table :bookmarks, comment: 'ブックマーク' do |t|
      t.integer :user
      t.integer :post

      t.timestamps
    end
    # add_foreign_key :参照先テーブル, :参照元テーブル
    add_foreign_key :bookmarks, :user
    add_foreign_key :bookmarks, :post
    add_index :bookmarks, [:user_id, :post_id], unique: true
end

以下の2つが注意点です。

  • referencesを使わない場合、カラムにforeign_key: trueを記述しても外部キー制約にはならない。add_foreign_keyで外部キー制約をつける必要あり
  • add_foreign_keyで外部キー制約をつけた場合、インデックスも自動で貼られるので、user_idとpost_idへadd_indexは不要

まとめ

今回は中間テーブルを作りたかったため、外部キーは必須となります。

最終的に以下のマイグレーションファイルになりました(名称は仮名)

# UserとPostの中間テーブルとしてBookmarkを作る
class CreateBookmarks < ActiveRecord::Migration[6.1]
  def change
    create_table :bookmarks, comment: 'ブックマーク' do |t|
      t.references :user, null: false, foreign_key: true
      t.references :post,   null: false, foreign_key: true

      t.timestamps
    end
    add_index :bookmarks, [:user_id, :post_id], unique: true
end

referencesを使うとデフォルトでインデックスは貼ってくれるが、それ以外の制約は自分で付与する必要がある、と理解できました。

referencesを使いこなせるようになると、マイグレーションファイルをとても効率的に書けるので、しっかりマスターしておきましょう。

また、以下の記事ではワンランク上のRailsエンジニアになりたいと考えている方向けにおすすめの技術書を紹介しています。

こちらの記事もぜひ読んでみてください。

あわせて読みたい
【実務経験1年以上向け】Rubyで設計を学べる技術書3選 Rubyで設計を学べる技術書を知りたくないですか?この記事ではRubyエンジニア向けにサンプルコードがRubyで書かれていて設計を学べる技術書を3つ紹介しています。自分に必要なのはどの1冊なのか、ぜひ考えてみてください。
参考文献
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

未経験でSESから従業員300名以上の自社開発企業に転職しました。業務や個人開発で直面した問題や、転職・学習の経験を発信していきます。

コメント

コメントする

目次