LoginSignup
0
0

More than 1 year has passed since last update.

【Rails】既存Userモデルのカラムと,deviseで生成したUserモデルのカラムが重複し,エラーとなったときの対応

Posted at

はじめに

deviseの導入時に遭遇したエラーと対処法について記事にしました.初学者の学習の一助となれば幸いです.

環境

Ruby 3.1.2
Rails 6.1.7

前提

以下のコマンドで既にUserモデルを作成しており,データベースにemailカラムをデータベースに適用済みという状況で,deviseを導入しエラーが発生しました.

コマンド
rails g model User (略) email:string
rails db:migrate

個人開発を前提にしてます.

エラー内容

devise導入のため,Gemfileにgem 'devise'を記述後,以下のコマンドを実行したところ,以下のエラーが発生しました.

コマンド
bundle install
rails g devise:install
rails g devise User
rails db:migrate
エラー内容
== 20220928040542 AddDeviseToUsers: migrating =================================
-- change_table(:users)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: duplicate column name: email
(略)

エラーメッセージを確認するとduplicate column name: emailとあり,emailというカラムが重複しているという内容です.前述のように既存のUserモデルのemailカラムをデータベースに適用済みだったことが原因でした.

解決策

既存のUserモデルのemailカラムを削除します.
対応の流れは以下となります.

  1. マイグレーションファイルをロールバックする.
  2. マイグレーションファイルを直接編集する.
  3. マイグレーションファイルをデータベースに適用する.

1. マイグレーションファイルをロールバックする.

マイグレーションファイルを直接編集するためには,データベースに未適用となっている必要があります.まずは,以下のコマンドを実行し,マイグレーションファイルのデータベースへの適用状態を確認します.

コマンド
rails db:migrate:status
実行結果
(略)
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20220928040334  Create users
  down    20220928040542  Add devise to users

既存のUserモデルのマイグレーションファイルはStatusupとなっており,データベースへ適用されていることを確認しました.
この状態ではマイグレーションファイルを直接編集できません.
マイグレーションファイルをデータベースへ未適用とするため,以下のコマンドでロールバックを行います(Statusdownにする).

コマンド
rails db:migrate:down VERSION=20220928040334
実行結果
== 20220928040334 CreateUsers: reverting ======================================
-- drop_table(:users)
   -> 0.0061s
== 20220928040334 CreateUsers: reverted (0.0152s) =============================

再度,データベースへの適用状態を確認します.

コマンド
rails db:migrate:status
実行結果
(略)
 Status   Migration ID    Migration Name
--------------------------------------------------
  down    20220928040334  Create users
  down    20220928040542  Add devise to users

Statusdownになっていることを確認できました.これでマイグレーションファイルの直接編集が可能になりました.

2. マイグレーションファイルを直接編集する.

以下のt.string :emailを削除します.

db/migrate/20220928040334_create_users.rb
class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :email #emailカムを削除します.
      (略)
      t.timestamps
    end
  end
end

3. マイグレーションファイルをデータベースに適用する.

以下のコマンドでデータベースへ適用します.

コマンド
rails db:migrate
実行結果
(略)
== 20220928040334 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0029s
== 20220928040334 CreateUsers: migrated (0.0030s) =============================

== 20220928040542 AddDeviseToUsers: migrating =================================
-- change_table(:users)
   -> 0.0053s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0013s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0006s
== 20220928040542 AddDeviseToUsers: migrated (0.0074s) ========================

最後に,データベースへの適用状態を確認します.

コマンド
rails db:migrate:status
実行結果
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20220928040334  Create users
   up     20220928040542  Add devise to users

データベースへの適用が確認できました.
以上で完了です.

注意点

今回は個人開発という前提のため,マイグレーションファイルを直接編集する方針を取りましたが,複数人による共同開発では,マイグレーションファイルを直接編集すると混乱を招く可能性があるため,新規にマイグレーションファイルを作成してカラムを削除する必要があります.
以下,Railsガイドから引用です.

一般に、既存のマイグレーションを直接変更するのはよくありません。既存のマイグレーションを変更すると、自分自身はもちろん、共同作業者も余分な作業を強いられます。さらに、既存のマイグレーションがproduction環境で実行中の場合、ひどい頭痛の種になるでしょう。既存のマイグレーションを直接修正するのではなく、修正用のマイグレーションを新たに作成してそれを実行するのが正しい方法です。これまでコミットされてない(より一般的に言えば、これまでdevelopment環境以外にデプロイされたことのない)マイグレーションを新たに生成し、それを編集するのが害の少ない方法です。

以上です.
皆さんの学習の一助となれば幸いです.
至らない点ありましたらご連絡いただければと思います.

参考

0
0
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
0
0