LoginSignup
3
4

More than 5 years have passed since last update.

初心者が送る Rails での PG::DuplicateTable: ERROR の解決方法まとめ

Last updated at Posted at 2019-03-22

はじめに

こんにちは!
見習いエンジニアの 古内 です!

以前、一度作成したモデルを削除し、再度同じ名前モデルを作成したときにうまくいかず、詰まってしまったことがあったので、その解決方法を実演しながら解説をさせていただきます。

私自身も初心者なのでこの解決方法は完璧ではないかもしれませんが、慣れていない人でもわかりやすいように説明できるようがんばります!

環境

  • Ruby 2.5.1
  • Ruby on Rails 5.2.2
  • Docker
  • Doker Compose

実演

準備

では環境の準備から始めましょう。
私はこちらを参考に環境構築をしました。
簡単に Rails 開発環境の構築ができるので、みなさんも活用してみてください!( こちらを使うときは最後の Docker Compose の起動まで進めてください )

作業開始

まずはモデルを作成し、

$ rails g model User

マイグレートします。

$ rails db:migrate

User モデルができました。

user.rb
class User < ApplicationRecord
end

これを一度削除します。

$ rails destroy model User

再度 User モデルを作成してみましょう。

$ rails g model User

マイグレートします。

$ rails db:migrate

すると、

== 20190321053454 CreateUsers: migrating ======================================
-- create_table(:users)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DuplicateTable: ERROR:  リレーション"users"はすでに存在します
: CREATE TABLE "users" ("id" bigserial primary key, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)

このようなエラー文が出てしまい、 User モデルを作成できません。

対策

User モデルを削除したときに、それが DB 側に伝わっていなかったことが問題だったです。
では解決してみましょう!

まず作成したマイグレーションファイルを削除します。

$ rails destroy migration create_users

続いて DB 側にモデルを削除したことを伝えるマイグレーションファイルを作成します。

$ rails g migration drop_table_users

続いて作成したマイグレーションファイルに以下のように追加してください。

20190321063950_drop_table_users.rb
class DropTableUsers < ActiveRecord::Migration[5.2]
  def change
    drop_table :users #追加
  end
end

これを追記することで DB 側のテーブルを削除できます。

マイグレートします。

$ rails db:migrate

先程使ったマイグレーションファイルを削除しましょう。

$ rails destroy migration drop_table_users

ではもう一度 User モデルを作成し、マイグレートしてみましょう。

$ rails g model user
$ rails db:migrate

これで User モデルを再度作成できました!

解説

今回の原因は User モデルを削除したときに、 DB 側にそれが伝わっていなかったことでした。
「なぜ作成するときは大丈夫なのに、削除するときはだめなの?」と思う方もいると思います。
これはマイグレートに原因があります。

図にすると、


   Rails 側    migrate      DB 側
User model 作成   -------->   User table 作成


   Rails 側            DB 側
User model を削除        User table が存在


   Rails 側    migrate      DB 側
User model 作成   -------->   User table はすでに存在


このようなことが起きているためエラー文が出てしまったのです。

ここでテーブルを削除するマイグレートを実行すると、


   Rails 側       migrate         DB 側
User model 作成     ------------->     User table 作成


   Rails 側                   DB 側
User model を削除              User table が存在


   Rails 側       migrate         DB 側
drop_table_user 作成   ------------>     User table を削除


   Rails 側       migrate         DB 側
User model 作成     ------------->     User table 作成


となり、再度 User モデルを作成できるようになります。

ちなみにマイグレートを実行すると、db/migrate ディレクトリにあるマイグレーションファイルを上から逐一 DB に反映させていくので、ここで整合性が取れていないとエラーが起きてしまいます。 ( テーブル削除のマイグレーションファイルを削除したのもこのため。テーブルを削除が完了したら、次のマイグレート実行時、削除対象がないためエラーの原因になる。 )

最後に

マイグレーション周りは複雑でわかりにくいです。
私もモデルとテーブルが別のものだと理解したり、整合性を取るようにするまでは大変でした。

モデル = DB の設計図
テーブル = モデルをもとに実際に作られたもの

と考えればわかりやすいかもしれません。

3
4
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
3
4