5

我有一个 Rails 应用程序,我在其中使用设计和偏执狂宝石。
我在 postgres db 中有一个用户表,它在电子邮件列上有唯一的验证。我正在使用偏执狂进行软删除,问题是当我删除用户然后使用已删除用户的电子邮件创建用户时会引发错误PG::UniqueViolation: ERROR
我已经阅读过这个并且知道这可以使用rails的部分索引功能来解决。

http://scottsmerchek.com/2015/08/03/taking-the-d-out-of-crud/

https://devcenter.heroku.com/articles/postgresql-indexes#partial-indexes

我该如何实施?
抱歉格式错误,从手机输入。

4

4 回答 4

3

因为您将用户删除为软删除,因此电子邮件不会从数据库中删除,所以只有一个用户属性is_deleted设置为 true。

PG::UniqueViolation: ERROR立即解决,您必须在字段 email 和 deleted_at 上创建唯一索引,因此您的迁移将是

class AddUniqueIndexToUsers < ActiveRecord::Migration
  def change
    remove_index :users, column: :email
    add_index :users, [:email, :deleted_at], unique: true
  end
end
于 2016-09-05T14:56:24.173 回答
0

正好:

class AddUniqueIndexToUsers < ActiveRecord::Migration
  def change
    remove_index :users, column: :email
    add_index :users, :email, unique: true, where: 'deleted_at IS NULL'
  end
end
于 2021-05-31T12:59:49.010 回答
0

UNIQUERakesh 的回答是错误的,并且将允许在数据库中重复,因为当其中一个值是NULL(并且默认情况下是)deleted_at时,复合索引将失败。NULL

要完成这项工作,您实际上需要以相反的方式将这种细微差别与唯一索引一起使用,您可以拥有一个整数列,比如acive:tinyint (default 1)和这样的复合索引:

add_index :users, [:email, :active], unique: true

创建新用户时不需要特殊操作,因为该active列的默认值为1. 但是每次删除记录时,除了设置 ,deleted_at还需要active设置NULL。这样,您可以只拥有一个活动记录,并使用相同的电子邮件地址删除许多记录。

在 PostgreSQL 或 MySQL > 8.0.13 中,您可以在没有此附加列的情况下工作,并使用如下功能索引:

CREATE UNIQUE INDEX unique_email
                 ON users (email, (IF(deleted_at IS NULL, 1, NULL)));

结果将与active列的示例类似。删除记录后,唯一索引将停止为此记录工作,从而允许您拥有多个相同的已删除记录email

于 2021-03-24T12:18:01.800 回答
0

它会在 Postgresql 上失败,可能的解决方案是

class AddUniqueIndexToUsers < ActiveRecord::Migration
  def change
    remove_index :users, column: :email
    add_index :users, [:email, :deleted_at], unique: true, where: "deleted_at is null"
  end
end

参考https://www.ironin.it/blog/partial-unique-indexes-in-postgresql-and-rails.html

于 2021-04-13T16:04:30.467 回答