2016-07-04 92 views
1

升级到Rails 5.0,从4.2我收到以下错误后:Ruby on Rails的5.0升级与迁移用户表冲突

PGError: ERROR: column “email” of relation “users” already exists

rails db:migrate 
== 20160703164716 AddDeviseToUsers: migrating ================================= 
-- change_table(:users) 
rails aborted! 
StandardError: An error has occurred, this and all later migrations canceled: 

PG::DuplicateColumn: ERROR: column "email" of relation "users" already exists 
: ALTER TABLE "users" ADD "email" character varying DEFAULT '' NOT NULL 
/Users/my_username/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `async_exec' 
/Users/my_username/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `block in execute' 

阅读下列两个堆栈溢出的帖子后

Devise migration on existing model

我的问题是哪个解决与用户选项卡发生数据库冲突的最佳方法乐?

最好是编辑现有的迁移文件,如20160703164716 AddDeviseToUsers迁移,还是建议进行新的迁移?

什么是进行新迁移的命令和此迁移的最佳名称,以防止在我的开发和基于Heroku的生产环境中发生数据库冲突?

def self.up 
    change_table(:users) do |t| 
    t.recoverable 
    t.trackable 
    # rememberable uses remember_token, but this field is different 
    t.rename :remember_token_expires_at, :remember_created_at 
    # these fields are named differently in devise 
    t.rename :crypted_password, :encrypted_password 
    end 
end 

以上是从第二篇文章中建议的建议代码。

你会如何利用这段代码并从中做出新的迁移?

研究迁移后,我已经做了以下迁移:

rails g migration change_data_type_for_users 

生成,我根据我的理解上述错误进行提示在用户领域修复编辑的新移民。新的迁移代码:

class ChangeDataTypeForUsers < ActiveRecord::Migration[5.0] 
    def change 
    change_table(:users) do |t| 
     t.string :email,    :null => false, :default => "" 
    end 
end 

运行rails db:migrate后收到相同的错误。我究竟做错了什么?我现在应该回滚还是编辑新迁移?

我已经找到了这个堆栈溢出文章。 (Rails 4 Ruby 2.00 Devise migration on existing User Model fails) 这是正确的道路吗?将删除数据库删除所有的数据库数据?

另一个发现这里导致相信如果执行rake db:reset会破坏我的数据库中的数据。这样做是否重新创建数据库?目前还不清楚,从后面的文章看来,如果所有的数据都被破坏,将会非常有害。我们只想修复一个表中的一个字段。

Difference between rake db:migrate db:reset and db:schema:load

我真的想回答我的问题所以也许这种模式使得一些区别就是除了似乎已经被ActiveAdmin创建的用户模式:

class AdminUser < ApplicationRecord 
    # Include default devise modules. Others available are: 
    # :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, 
     :recoverable, :rememberable, :trackable, :validatable 
end 
+0

当你从错误信息看,“问题”是您要添加电子邮件列,但它已存在于您的用户表中。迁移是好的,似乎问题在于数据库版本(实际上已包括电子邮件列)和迁移的不同步。尝试重置数据库(以防您没有任何敏感数据)。 –

+0

Paul,非常感谢。不幸的是,我有敏感的数据,这是恐惧或重置分贝。有没有办法回到这一列,并通过命令行删除它?我发现很多链接来重置数据库(http://stackoverflow.com/questions/10301794/difference-between-rake-dbmigrate-dbreset-and-dbschemaload),但我担心数据库中的其他部分的数据这是敏感的。 – March

+0

你可以删除列,是的。运行'rails db',然后你得到你的数据库控制台。读取您的数据库引擎语法以更改表并删除列(除非它是sqllite) –

回答

1

在你的情况下,记住你正在试图改变数据库中存在的列,就像你正在创建一个新的那样。

t.string :email, :null => false, :default => "" 

,您可以更改该行

t.change :email, :string, :null => false, :default => "" 

您块的内部,知道“T”是你的用户表

+0

这工作谢谢@保罗布拉诺夫和@xploshioOn! – March