Подтвердить что ты не робот

Rails, создающий миграцию для добавления столбцов в таблицу, вызывает ошибку при запуске rake db: migrate

У меня есть модель, созданная с именем "users", и я создал новую миграцию, чтобы добавить некоторые столбцы в таблицу users. Теперь, когда я запускаю rake db: migrate, я получаю ошибку ниже b/c, пытаясь снова создать таблицу users

$ rake db:migrate
==  DeviseCreateUsers: migrating ==============================================
-- create_table(:users)
rake aborted!
An error has occurred, all later migrations canceled:

Mysql::Error: Table 'users' already exists: CREATE TABLE `users`.....

Почему он пытается снова создать таблицу?

Здесь команда, которую я использовал для создания новой миграции

$ rails generate migration AddDetailsToUsers home_phone:decimal cell_phone:decimal work_phone:decimal birthday:date home_address:text work_address:text position:string company:string

Новая миграция выглядит следующим образом:

class AddDetailsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :home_phone, :decimal
    add_column :users, :cell_phone, :decimal
    add_column :users, :work_phone, :decimal
    add_column :users, :birthday, :date
    add_column :users, :home_address, :text
    add_column :users, :work_address, :text
    add_column :users, :position, :string
    add_column :users, :company, :string
  end
end

ИЗМЕНИТЬ

20120511224920_devise_create_users

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :email,              :null => false, :default => ""
      t.string :username,           :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
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Encryptable
      # t.string :password_salt

      ## 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 # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## Token authenticatable
      # t.string :authentication_token


      t.timestamps
    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
    # add_index :users, :authentication_token, :unique => true
  end
end

20120619023856_add_name_to_users

class AddNameToUsers < ActiveRecord::Migration
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end

20121031174720_add_details_to_users.rb

class AddDetailsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :home_phone, :decimal
    add_column :users, :cell_phone, :decimal
    add_column :users, :work_phone, :decimal
    add_column :users, :birthday, :date
    add_column :users, :home_address, :text
    add_column :users, :work_address, :text
    add_column :users, :position, :string
    add_column :users, :company, :string
  end
end
4b9b3361

Ответ 1

Rails отслеживает миграцию в таблице "schema_migrations" вашей базы данных. Если нет записи для "20120511224920", которая является миграцией Devise, она попытается запустить ее снова, которая, как представляется, уже существует.

Вы можете добавить это вручную в таблицу, если это так.

Ответ 2

Ошибка говорит о том, что она пытается снова запустить первоначальную миграцию DeviseCreateUsers и не может, поскольку таблица пользователей уже существует.

Чтобы исправить это, вы можете запустить миграцию вниз для DeviseCreateUsers, а затем выполнить миграцию как обычно. Вы можете сделать это с помощью

rake db:migrate:down VERSION=20121031XXXXXXXX
rake db:migrate

Где 20121031XXXXXXXX - это отметка даты имени миграции. Другими словами, вы будете иметь миграцию с именем 20120410214815_devise_create_users.rb и скопируете штамп даты из имени файла и вставьте его в команду. Здесь Rails Guide on Migrations для справки.

Изменить: Это отмечено в комментариях, а всего лишь слово предупреждения. Выполнение переноса вниз для таблицы приведет к потере любых записей, которые есть в таблице. Я предполагаю, что вы работаете в режиме разработки, поэтому это не должно быть проблемой. Если вы находитесь в производстве, вам нужно будет предпринять дополнительные шаги для резервного копирования данных таблицы и перезагрузки после этого, иначе у вас будет плохой день (или, возможно, неделя).

Ответ 3

Можете ли вы попробовать создать новую базу данных, а затем перенести ее снова:

rake db:drop:all
rake db:create:all
rake db:migrate

Ответ 4

Итак, из того, что я собрал из этого:

  • У вас уже была модель пользователя
  • У вас есть версия этого в производстве
  • Вы запускали по умолчанию rails generate devise: install
  • Затем вы запустили рельсы, генерирующие dev. Пользователь

Я надеюсь, что:

  • Вы используете источник управления
  • Вы часто проверяете код

ПРИМЕЧАНИЕ. Если нет, вы узнаете, зачем вам это нужно.

Отмените свой код до того, как вы создали Devise

Надеюсь, вы можете просто создать новую песочницу точки прямо перед генерацией. Если нет, скопируйте каталог проекта и сделайте это вручную. Единственный другой вариант - это вручную отредактировать все файлы, созданные Devise.

Повторите создание своего поколения

  • readd gem 'devise' в ваш Gemfile
  • рельсы создают devise: install
  • рельсы генерируют конструкцию MODEL

Убедитесь, что модель не существует! Если вы этого не сделаете, вы попадаете в проблему, которую вы в настоящее время имеете.

Перенос текущих пользователей из одной модели в другую

Если вы можете создать script, чтобы полностью перенести данные аутентификации из вашей старой пользовательской модели в новую, хорошо для вас. Если вы используете другой алгоритм хэширования из Devise для вашей текущей проверки подлинности, вы собираетесь либо аннулировать все свои пароли, либо потребовать от своих пользователей создания нового пароля с помощью кода подтверждения в своем письме или вы можете перенести пользователей по мере их регистрации Первый метод - чистый, полный и грубый. Второй метод является уродливым, неполным и бесшумным. Выберите свой метод, как вам нравится.

Изменить: вы, вероятно, можете найти способ настроить Devise для использования своего алгоритма. Это, вероятно, будет еще лучше, но немного больше работы и довольно хрупкой.

Другое дело, что ваша модель проверки подлинности не должна быть перегружена данными учетной записи. У вас должна быть модель, которая обрабатывает только аутентификацию, которая имеет модель данных учетной записи account_a, которая хранит все, что вы можете отслеживать в отношении учетных записей.

Ответ 5

используйте методы "вверх-вниз". Это будет полезно для отката и выполнения определенного файла миграции.

Пожалуйста, следуйте синтаксису..

  class AddDetailsToUsers < ActiveRecord::Migration
    def self.up
      add_column :users, :home_phone, :decimal
      add_column :users, :cell_phone, :decimal
      add_column :users, :work_phone, :decimal
      add_column :users, :birthday, :date
      add_column :users, :home_address, :text
      add_column :users, :work_address, :text
      add_column :users, :position, :string
      add_column :users, :company, :string
   end

   def self.down
      remove_column :users, :home_phone
      remove_column :users, :cell_phone
      remove_column :users, :work_phone
      remove_column :users, :birthday
      remove_column :users, :home_address
      remove_column :users, :work_address
      remove_column :users, :position
      remove_column :users, :company
   end
  end


    In this case please try to migrate using version number.

Как rake db: migrate: down VERSION = номер версии # номер перевода - это версия, которую вы хотите перенести.

Ответ 6

Я предполагаю, что вы запустили rails generate devise user sometime, который сгенерировал DeviseCreateUsers. Если вы уже создали таблицу User model и users, вы можете удалить сгенерированный файл миграции из db/migrate.

Ответ 7

Проверьте некоторые переменные среды, которые могут поставлять неожиданное значение для версии вашей миграции. Я нашел старый вопрос о переполнении стека (и простить меня, если он устарел), где db:migrate уничтожает таблицу, вместо применения существующей новой миграции,

В итоге они обнаружили, что переменная окружения вызывала db:migrate для запуска с параметром версии "0", который функционально эквивалентен rake db:migrate:down

Возможно ли, что ваша ситуация может быть вызвана неожиданно измененной версией для включения или сопоставления предыдущей миграции DeviseCreateUsers?

Ответ 8

просто попробуйте

в первом файле

create_table(:users), :force => true do |t|

это переопределит любую другую таблицу

Ответ 9

В соответствии с тем, что вы сказали, вы использовали эту команду для создания новой миграции

$rails сгенерировать миграцию AddDetailsToUsers home_phone: decimal cell_phone: decimal work_phone: decimal birthday: date home_address: text work_address: text position: string company: string

Я не уверен, что это просто опечатка, но это должно быть "AddDetailsToUser", а не "Пользователи". Просто проверьте еще раз, и мы сможем вам помочь. Это для разрабатываемой модели. Когда вы указываете User, в db он ищет пользователей.

Ruby on Rails следуют лингвистическому соглашению. имя_таблицы - это Plural, а имя_модель - Singular. Вы должны использовать имя модели в используемой вами команде.

Если вы хотите использовать имя_таблицы, используйте этот

rails g migration add_details_to_users home_phone: decimal...... и т.д.

Ответ 10

И если вам нужно выполнить некоторые грязные миграции вручную:

class A < ActiveRecord::Migration
  def up
    add_column :images, :name
  end
end

A.new.migrate(:up)