【Rails】中間テーブルを作る際はユニーク制約に注意しよう

Ruby on Railsで中間テーブルの実装方法を探していませんか?

仕事で多対多の関係を避けるために中間テーブルを実装しましたが、ユニーク制約を注意深く付与しないと予期せぬトラブルを引き起こしかねません。

そこでこの記事では、実務経験をもとに中間テーブルの実装方法とユニーク制約の正しい付け方を解説します。

最後まで読めば、中間テーブルを正しく効果的に実装できるようになります。

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

この記事で解説するRailsのバージョンは7.1.3.4です!

目次

中間テーブルを作る際はユニーク制約に注意しよう

手順は以下の2ステップです。

  1. マイグレーションファイルの作成と実行
  2. モデルファイル側でもユニーク制約を設定

順番に確認します。

前提
この記事では、ユーザ(User)が求人(Job)をブックマーク(Bookmark)する機能を想定し、Bookmarkテーブルを作ると仮定します。
ブックマークにおいて、ユーザと求人の組み合わせは一意となる必要があります。

1. マイグレーションファイルの作成と実行

まずは以下のコマンドでマイグレーションファイルを作成します。

$ rails g migration CreateBookmarks user:references job:references

中間テーブルのデータの組み合わせを一意にしたい場合、外部キーの組み合わせにユニーク制約をつけましょう(複合インデックス)

今回の場合、user_id と job_id のペアに対して設定します。

class CreateBookmarks < ActiveRecord::Migration[6.1]
  def change
    create_table :bookmarks do |t|
      t.references :user, null: false, foreign_key: true
      t.references :job,  null: false, foreign_key: true

      t.timestamps
    end
    add_index :bookmarks, [:user_id, :job_id], unique: true  # ユニーク制約を設定
  end
end

このマイグレーションファイルを実行すれば、データベース側にユニーク制約が設定されます。

$ rails db:migrate

2. モデルファイル側でもユニーク制約を設定

次にモデルファイル側でもユニーク制約を設定します。

以下はapp/models/bookmark.rbの実装例です。

class Bookmark < ActiveRecord::Base
  belongs_to :user
  belongs_to :job

 # scope付きでユニーク制約を設定
  validates :user_id, presence: true, uniqueness: { scope: :job_id }
  validates :job_id,   presence: true
end

scopeを指定することで、user_id と job_id のペアが一意に限定されます。(片方だけでOK)

もしscopeを指定しなかったら、各ユーザは複数の求人をブックマークできなくなってしまうため、要注意です。

class Bookmark < ActiveRecord::Base
  belongs_to :user
  belongs_to :job

 # scopeを指定しないと各ユーザはブックマークを2つ以上できなくなる
  validates :user_id, presence: true, uniqueness: true
  validates :job_id,   presence: true
end

ユニーク制約をマイグレーションとモデルファイルの両方に書く理由

ユニーク制約はマイグレーションファイルとモデルファイルの両方に記述する必要があります。

この点については、以前にも疑問に思ったため、次の記事にまとめてあります。

あわせて読みたい
【Rails】ユニーク制約はマイグレーションファイルとモデルファイルの両方に書く 業務でRailsのテーブル実装をしていたんですが、ユニーク制約をマイグレーションファイルとモデルファイルのどちらに記述すれば良いか迷ってしまいました。 そこでこの...

まとめ

この記事では中間テーブルの実装方法と、データの組み合わせを一意としたい場合の注意点をまとめました。

ユニーク制約をつけ忘れて後から追加でマイグレーションを実行するのはとても面倒です。

この記事のやり方をしっかり覚えておきましょう。

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

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

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

この記事を書いた人

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

コメント

コメントする

目次