はじめに
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. マイグレーションファイルをロールバックする.
マイグレーションファイルを直接編集するためには,データベースに未適用となっている必要があります.まずは,以下のコマンドを実行し,マイグレーションファイルのデータベースへの適用状態を確認します.
rails db:migrate:status
(略)
Status Migration ID Migration Name
--------------------------------------------------
up 20220928040334 Create users
down 20220928040542 Add devise to users
既存のUserモデルのマイグレーションファイルはStatus
がup
となっており,データベースへ適用されていることを確認しました.
この状態ではマイグレーションファイルを直接編集できません.
マイグレーションファイルをデータベースへ未適用とするため,以下のコマンドでロールバックを行います(Status
をdown
にする).
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
Status
がdown
になっていることを確認できました.これでマイグレーションファイルの直接編集が可能になりました.
2. マイグレーションファイルを直接編集する.
以下のt.string :email
を削除します.
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環境以外にデプロイされたことのない)マイグレーションを新たに生成し、それを編集するのが害の少ない方法です。
以上です.
皆さんの学習の一助となれば幸いです.
至らない点ありましたらご連絡いただければと思います.
参考