Help us understand the problem. What is going on with this article?

複合ユニークインデックスに含まれる外部キー1個を別の外部キーに置き換えるマイグレーション

More than 1 year has passed since last update.

Rails 5.1を前提とします。

やりたいこと

次のようなDBスキーマがあるとします。

schema.rbの抜粋
create_table "categories", force: :cascade do |t|
  # ...
end

create_table "products", force: :cascade do |t|
  # ...
end

create_table "sub_products", force: :cascade do |t|
  # ...
end

create_table "category_products", force: :cascade do |t|
  t.bigint "category_id"
  t.bigint "product_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["category_id", "product_id"], unique: true
  t.index ["product_id"]
end

# ...

add_foreign_key "category_products", "categories"
add_foreign_key "category_products", "products"

このときに、category_products の複合ユニークインデックス [:category_id, :product_id][:category_id, :sub_product_id] に変更するマイグレーションを作りたい場合を考えます。

ここで、マイグレーションはリバーシブル(マイグレーションを up, down したときに正しく前後のDBスキーマに変更できること)になるように気をつけます。

やりかた

change_table を使って、次のようなマイグレーションを作ります。

class ChangeReferenceInCategoryProducts < ActiveRecord::Migration[5.1]
  def change
    change_table :category_products do |t|
      t.remove_index column: [:category_id, :product_id], unique: true
      t.remove_references :product, foreign_key: true
      t.references :sub_product, foreign_key: true
      t.index [:category_id, :sub_product_id], unique: true
    end
  end
end

まず、remove_index で複合ユニークインデックスを削除します。このときに unique: true を指定しておかないと、db:migrate:down 時に、この複合インデックスをユニーク制約が付いた状態で復元できません。

その後、remove_references で外部キーカラム product_id を削除します。

この後は新しい外部キーカラムと複合ユニークインデックスを作ります。削除とは逆に、カラム作成→複合インデックス作成の順番で実行しており、マイグレーション全体として処理が対称になります。

以上の方法で、db:migrateup, down を行き来できるようになります。

参考

pepabo
「いるだけで成長できる環境」を標榜し、エンジニアが楽しく開発できるWebサービス企業を目指しています。
https://pepabo.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした