我最初进行了这次迁移:
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
但在我的应用程序中,用户无需oauth身份验证即可使用omniauth,用户名和密码登录。因此,在许多情况下,uid和provider将为null。所以我创建了以下迁移:
def change
change_column_default :users, :provider, nil
change_column_default :users, :uid, nil
end
但是当我尝试在Rails中将提供者或uid设置为nil时,我得到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 :(得分:0)
您在第一次迁移中将列设置为 null:false ,这会导致PG :: NotNullViolation异常。需要将其设置为true以允许两列中都包含空值。编写新的迁移以设置null:true应该按如下方式解决问题。
def change
change_column_null :users, :provider, true
change_column_null :users, :uid, true
end
同样低于索引可能不起作用(RecordNotUnique异常会因为设置唯一:true而引发),因为您将有多行同时具有空值的uid和provider。因此需要删除此索引。
add_index :users, [:uid, :provider], unique: true
答案 1 :(得分: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