[英]Rails creating migration to add columns to table causes error when running 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
Rails在数据库的“schema_migrations”表中跟踪迁移。 除非存在“20120511224920”的条目,即Devise迁移,否则它将尝试再次运行它,它似乎已经存在。
如果是这种情况,您可以手动将其添加到表中。
该错误表明它正在尝试再次运行原始DeviseCreateUsers迁移,因为users表已经存在而无法运行。
要解决此问题,您可以运行DeviseCreateUsers
的向下迁移,然后正常运行迁移。 你可以这样做:
rake db:migrate:down VERSION=20121031XXXXXXXX
rake db:migrate
其中20121031XXXXXXXX
是迁移名称的日期戳。 换句话说,您将进行名为20120410214815_devise_create_users.rb
的迁移,并从文件名中复制日期戳并将其粘贴到命令中。 这是关于迁移的Rails指南以供参考 。
编辑:这在评论中注明,但只是一个警告。 对表执行向下迁移将丢失表所具有的任何条目。 我假设你在开发模式下运行,所以这应该不是问题。 如果你正在制作中,你将需要采取额外的步骤来备份表数据并在之后重新加载它,否则你将会有糟糕的一天(或者可能是一周)。
您可以尝试创建一个新的数据库,然后再次迁移它:
rake db:drop:all
rake db:create:all
rake db:migrate
从我从中收集到的内容:
我希望:
注意:如果没有,您将了解为什么需要这样做。
在生成Devise之前将代码还原到
希望您可以在生成Devise之前创建一个新的沙箱。 如果没有,请复制项目目录并手动完成。 唯一的另一个选项是手动编辑Devise生成的所有文件。
重新运行你的Devise一代
确保模型不存在! 如果你不这样做,你会遇到你目前遇到的问题。
将当前用户从一个模型迁移到另一个模型
如果您可以生成脚本以将身份验证信息从旧用户模型完全移动到新用户模型,那么对您有好处。 如果您使用Devise的其他哈希算法进行当前身份验证,那么您将要么使其所有密码无效并要求您的用户使用其电子邮件中的确认代码创建新密码,或者您可以在用户登录时迁移用户in。第一种方法是干净,完整和粗鲁。 第二种方法是丑陋,不完整和沉默。 选择你喜欢的方法。
编辑:您可能会找到一种方法来自定义Devise以使用您的算法。 这可能会更好,但更多的工作和相当脆弱。
另一件事是您的身份验证模型不应该超载帐户数据。 您应该有一个仅处理身份验证的模型,该身份验证具有存储您可能要跟踪帐户的任何内容的帐户数据模型。
使用上下方法。 它对于回滚和运行特定的迁移文件很有用。
请遵循语法..
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是您要迁移的版本。
我猜你有时会运行rails generate devise user
generate DeviseCreateUsers
rails generate devise user
生成DeviseCreateUsers
。 如果已创建用户模型和用户表,则可以从db / migrate中删除生成的迁移文件。
检查可能为迁移版本提供意外值的一些环境变量。 我在Stack Overflow上发现了一个老问题 (并且如果它已经过时,请原谅我) db:migrate
正在破坏表,而不是应用现有的新迁移。
他们最终发现环境变量导致db:migrate
以版本参数“0”运行,这在功能上等同于rake db:migrate:down
是否可能由于意外更改版本以包含或匹配以前的迁移DeviseCreateUsers
而导致您的情况?
你试一试
在第一个文件中
create_table(:users), :force => true do |t|
这将覆盖任何其他表
根据您的说法,您使用此命令创建了新的迁移
$ 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遵循语言约定.table_name是Plural,但model_name是Singular。 您必须在您使用的命令中使用model_name。
如果要使用table_name,请使用此方法
rails g migration add_details_to_users home_phone:decimal ......等
如果您需要手动执行一些脏迁移:
class A < ActiveRecord::Migration
def up
add_column :images, :name
end
end
A.new.migrate(:up)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.