【解決法】rails db:migrateのエラー文SQLite3::SQLException: duplicate column name: カラム名

前にも同じ問題で悩んだので自分用に記事書きます。




```rails db:migrate```をした際にエラー文```SQLite3::SQLException: duplicate column name: email```と出ました。

そのままの直訳でテーブル内に同じカラム名のデータがあります、とのこと。


railsチュートリアルのアプリに[deviseを使ったメール認証機能](https://qiita.com/nekononeko_53/items/0af968c9617e404c45a1)を実装している際のエラーです。


調べたところ```schema.rb```がデータベースの中身を反映しているということでみたところ、かぶっている部分は分からず。




もう一度調べたところ、migrateファイル内にある複数のマイグレーションファイル内で指示がかぶっていてはいけない、とのこと。

とりあえず直近で作ったマイグレーションファイルの中にあったemailをコメントアウト。


```20200206081213_add_devise_to_users.rb
# frozen_string_literal: true

class AddDeviseToUsers < ActiveRecord::Migration[5.2]
  def self.up
    change_table :users do |t|
      ## Database authenticatable
       #t.string :email,              null: false, default: ""            ←この一行
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
       t.string   :confirmation_token
       t.datetime :confirmed_at
       t.datetime :confirmation_sent_at
       t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      # Uncomment below if timestamps were not included in your original model.
      # t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end

  def self.down
    # By default, we don't want to make any assumption about how to roll back a migration when your
    # model already existed. Please edit below which fields you would like to remove in this migration.
    raise ActiveRecord::IrreversibleMigration
  end
end

```


もう一回rails db:migrateしたら、次は

```
ArgumentError: Index name 'index_users_on_email' on table 'users' already exists
```
とのこと。
usersテーブルにある、インデックス名がindex_users_on_emailが被ってるということなのでそれらしきデータをまたまたコメントアウト。


```20200206081213_add_devise_to_users.rb
# frozen_string_literal: true

class AddDeviseToUsers < ActiveRecord::Migration[5.2]
  def self.up
    change_table :users do |t|
      ## Database authenticatable
       #t.string :email,              null: false, default: ""            ←さっきコメントアウトしたやつ
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
       t.string   :confirmation_token
       t.datetime :confirmed_at
       t.datetime :confirmation_sent_at
       t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      # Uncomment below if timestamps were not included in your original model.
      # t.timestamps null: false
    end

    #add_index :users, :email,                unique: true       ←名前的にこれが怪しいのでコメントアウト 
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end

  def self.down
    # By default, we don't want to make any assumption about how to roll back a migration when your
    # model already existed. Please edit below which fields you would like to remove in this migration.
    raise ActiveRecord::IrreversibleMigration
  end
end

```

で、rails db:migrateしたら成功しました。




## 個人的にわかったこと
・migrate内にあるマイグレーションファイルはデータベースにデータをいれるよう指示しているものである。（仕様書？説明書的なイメージ。）
マイグレーションファイルを最終的に作り上げる（指示通りデータベース内に入れる）のが rails db:migrateコマンド。
・migrate内にあるマイグレーションファイルで、指示が被っている（つまりすでにデータベースに入っているカラムを、新しく作ったマイグレーションファイルに書き込んでいる状態）とエラーが起きる。
・schemaファイルはデータベースの中身を写しているものであるので、schema内を変更してもデータベースを変更したことにはならない。
・エラーに気がつけるようにマイグレーションファイルは1つずつ追加して、被っているか確認するのがストレスへる。
・```ArgumentError: Index name 'index_users_on_email' on table 'users' already exists```がファイル内のadd_index :users, :email,                unique:trueを指しているものであること。