22

我创建了一个名为“users”的模型,并创建了一个新的迁移以将一些列添加到 users 表中。现在,当我运行 rake db:migrate 时,我在 b/c 下面得到错误,它正在尝试再次创建用户表

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

10 回答 10

12

Rails 在数据库的“schema_migrations”表中跟踪迁移。除非有“20120511224920”条目,即设计迁移,否则它将尝试再次运行它,它似乎已经存在。

如果是这种情况,您可以手动将其添加到表中。

于 2012-11-05T21:54:01.447 回答
6

该错误表示它正在尝试再次运行原始的 DeviseCreateUsers 迁移并且不能因为用户表已经存在。

要解决此问题,您可以运行向下迁移DeviseCreateUsers,然后正常运行迁移。你可以这样做:

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

20121031XXXXXXXX迁移名称的日期戳在哪里。换句话说,您将拥有一个名为的迁移20120410214815_devise_create_users.rb,并从文件名中复制日期戳并将其粘贴到命令中。这是 Rails Guide on Migrations 供参考

编辑:这在评论中注明,但只是一个警告。运行表的向下迁移将丢失该表的所有条目。我假设您正在开发模式下运行,所以这应该不是问题。如果您在生产中,则需要采取额外的步骤来备份表数据并在之后重新加载,否则您将度过糟糕的一天(或一周)。

于 2012-10-31T23:07:35.460 回答
5

您可以尝试创建一个新数据库然后再次迁移它:

rake db:drop:all
rake db:create:all
rake db:migrate
于 2012-11-05T07:45:05.820 回答
2

因此,根据我从中收集到的信息:

  • 你已经有一个用户模型
  • 你在生产中有这个版本
  • 你运行了一个默认的 rails generate devise:install
  • 然后你运行 rails generate devise User

我希望:

  • 您使用源代码控制
  • 你检查代码很多

注意:如果没有,您将了解为什么需要这样做。

将您的代码恢复到生成设计之前

希望您可以在生成设计之前创建一个点的新沙箱。如果没有,请复制您的项目目录并手动完成。唯一的其他选项是手动编辑 Devise 生成的所有文件。

重新运行您的设计生成

  • 将 gem 'devise' 读入你的 Gemfile
  • rails 生成设计:安装
  • rails 生成设计模型

确保该模型不存在!如果你不这样做,你就会陷入你目前遇到的问题。

将当前用户从一种模型迁移到另一种模型

如果您可以生成一个脚本以将身份验证信息从旧用户模型完全移动到新用户模型,那么对您有好处。如果您使用与 Devise 不同的哈希算法进行当前身份验证,那么您将使其所有密码无效并要求您的用户使用其电子邮件中的确认码创建新密码,或者您可以在用户登录时迁移他们第一种方法干净、完整、粗鲁。第二种方法是丑陋的、不完整的、沉默的。选择你喜欢的方法。

编辑:您可能会找到一种方法来自定义设计以使用您的算法。那可能会更好,但需要更多的工作并且相当脆弱。

另一件事是您的身份验证模型不应该因帐户数据而过载。您应该有一个只处理身份验证的模型,该模型具有帐户数据模型,该模型存储您可能想要跟踪的有关帐户的任何内容。

于 2012-11-06T03:29:27.520 回答
2

使用 up 和 down 方法。这对于回滚和运行特定的迁移文件很有用。

请按照语法..

  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=version number #version number 是您要迁移的版本。

于 2012-11-07T05:58:57.570 回答
1

我猜你跑了rails generate devise user某个时候生成了DeviseCreateUsers. 如果你已经创建了 User 模型和 users 表,你可以从 db/migrate 中删除生成的迁移文件。

于 2012-11-01T00:27:34.090 回答
1

检查可能为迁移版本提供意外值的一些环境变量。我在 Stack Overflow 上发现了一个老问题(如果它已经过时,请原谅我)在哪里db:migrate破坏了表,而不是应用现有的新迁移。

他们最终发现环境变量导致db:migrate以“0”的版本参数运行,这在功能上等同于rake db:migrate:down

您的情况是否可能是由于版本被意外更改为包含或匹配先前的迁移而导致的DeviseCreateUsers

于 2012-11-08T19:12:54.857 回答
0

你试一试

在第一个文件中

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

这将覆盖任何其他表

于 2012-11-06T07:28:34.983 回答
0

根据您所说,您使用此命令创建了一个新的迁移

$ rails 生成迁移 AddDetailsToUsers home_phone:decimal cell_phone:decimal work_phone:decimalbirthday:date home_address:text work_address:text position:string company:string

我不确定它是否只是一个错字,但它应该是“AddDetailsToUser”而不是“Users”。请再次检查,我们将能够为您提供帮助。这是用于设计生成的模型。当您提到用户时,它会在 db 中查找用户。

Ruby on Rails 遵循语言约定。table_name 是复数,而 model_name 是单数。您必须在使用的命令中使用 model_name。

如果你想使用 table_name 然后使用这个

rails g migration add_details_to_users home_phone:decimal......等

于 2013-12-26T06:13:49.240 回答
0

如果您需要手动进行一些脏迁移:

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

A.new.migrate(:up)
于 2014-10-14T22:27:05.357 回答