我想在列上指定唯一索引,但我还需要允许NULL
值(多条记录可以有NULL
值)。使用 PostgreSQL 进行测试时,我看到我可以有 1 条记录NULL
,但下一条记录会导致问题:
irb(main):001:0> u=User.find(5)
User Load (111.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 5]]
=> #<User id: 5, email: "a@b.com", created_at: "2013-08-28 09:55:28", updated_at: "2013-08-28 09:55:28">
irb(main):002:0> u.email=nil
=> nil
irb(main):003:0> u.save
(1.1ms) BEGIN
User Exists (4.8ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" IS NULL AND "users"."id" != 5) LIMIT 1
(1.5ms) ROLLBACK
=> false
因此,即使数据库允许,Rails 也会首先检查是否User
存在具有不同 id 且email
列设置为NULL
. 有没有一种方法不仅数据库可以允许它,而且 Rails 也不会像上面那样首先检查?
这个想法是用户不必输入电子邮件,但如果他们这样做,我需要能够通过他们的电子邮件找到用户。我知道我可以创建另一个模型来将用户与电子邮件相关联,但我更愿意采用上述方式。
更新email
:这是我为添加列而创建的迁移代码
class AddEmailToUsers < ActiveRecord::Migration
def change
add_column :users, :email, :string
add_index :users, :email, :unique => true
end
end
这是我添加到User
模型中的代码:
validates :email, uniqueness: true
我忘记了我已将validates
调用添加到User
模型中。因此,Rails 首先检查是有道理的。我想唯一的另一个问题是数据库拥有唯一索引和NULL
字段是否安全?有没有办法在 Rails 中指定我想验证电子邮件是唯一的,除非它是nil
?