2017-08-16 28 views
0

我本来这种迁移:轨移民工作唯一真实的,但允许空值

def change 
    add_column :users, :provider, :string, null: false, default: "email" 
    add_column :users, :uid, :string, null: false, default: "" 

    add_index :users, [:uid, :provider], unique: true 
    end 

但在我的应用程序,用户可以使用两个omniauth和用户名和密码,而不OAuth认证登录。因此,在许多情况下,uid和提供者将为空。所以,我创建了以下迁移:

def change 
    change_column_default :users, :provider, nil 
    change_column_default :users, :uid, nil 
    end 

但是,当我尝试设置提供商或UID在Rails的零,我得到一个PG::NotNullViolation: ERROR

u = User.first 
u.provider = nil 
u.save! 
    (0.4ms) BEGIN 
    SQL (1.5ms) UPDATE "users" SET "updated_at" = $1, "provider" = $2 WHERE "users"."id" = $3 [["updated_at", 2017-08-16 00:01:34 UTC], ["provider", nil], ["id", 1]] 
    (0.5ms) ROLLBACK 
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR: null value in column "provider" violates not-null constraint 
DETAIL: Failing row contains 

看来unique: true在迁移防止设置空值。我怎样才能解决这个问题?

回答

0

您在第一次迁移中将列设置为null:false导致PG :: NotNullViolation异常。这需要设置为true以允许两列中的空值。编写新的迁移以设置null:true应该如下解决问题。

def change 
    change_column_null :users, :provider, true 
    change_column_null :users, :uid, true 
end 

也低于指数可能无法正常工作(RecordNotUnique异常升高,因为它是一组唯一:真),你将有兼具uid和提供空值的多个行。所以这个指数需要被丢弃。

add_index :users, [:uid, :provider], unique: true 
+0

对于{:null => true},未定义的方法'to_sym':使用change_column时的哈希:users,:provider,null:true – Donato

+0

我编辑了我的答案。请立即检查,如果您使用rails 4.x版本,它应该可以正常工作。 – harika

0

除此之外:

def change 
    change_column :users, :provider, :string, null: true 
    change_column :users, :uid, :string, null: true 
    remove_index :users, [:uid, :provider] 
    end 

并随后将允许空值,但消除在数据库级别两个领域的约束,我这样做是在模型级:

validates :provider, uniqueness: { scope: :uid }, allow_nil: true 
相关问题